38
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Elaborato finale in Reti di Calcolatori Sviluppo di applicazioni Open Web Apps multipiattaforma Anno Accademico 2012/2013 Candidato: Marco Castelluccio matr. N46/1112

Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

  • Upload
    vonga

  • View
    215

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Elaborato finale in Reti di Calcolatori

Sviluppo di applicazioni Open Web Apps multipiattaforma

Anno Accademico 2012/2013 Candidato: Marco Castelluccio matr. N46/1112

Page 2: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di
Page 3: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

III

Indice

Capitolo 1. Open Web Apps 4

1.1 Vantaggi per gli utenti 15

1.2 Vantaggi per gli sviluppatori 23

1.3 App Manifest 25

1.4 Integrazione con le diverse piattaforme 32

1.5 Hosted apps 35

1.6 Packaged apps 36

1.7 Il sistema di sicurezza 38

Capitolo 2. Sviluppo di applicazioni 42

2.1 Presentazione di alcune API interessanti 42

2.1.1 TCPSocket API 44

2.1.2 Geolocation API 46

2.1.3 Apps API 49

2.1.4 Indexed Database API 53

2.1.5 Payments API 62

2.1.6 WebRTC 70

2.1.7 WebGL, FullScreen API, PointerLock API, Gamepad API, WebAudio API 72

2.2 Presentazione di alcuni tool di sviluppo interessanti 49

2.2.1 Remote debugger 53

2.2.2 Emscripten 62

Capitolo 3. Il desktop WebRuntime (WebRT) 42

3.1 Installazione 42

3.2 Architettura del WebRT 44

3.3 Funzionamento del WebRT 46

Bibliografia 199

Page 4: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

4

Capitolo 1

Open Web Apps

Open Web Apps è un progetto di Mozilla per la creazione di una piattaforma per

applicazioni basata completamente sul web.

Una webapp è semplicemente un sito, a cui è associato un insieme di metadati per la sua

descrizione, che può essere installato su un dispositivo e utilizzato come un'applicazione

nativa.

Una webapp è un'applicazione sviluppata con i linguaggi tipici del web (JavaScript,

HTML, CSS), che utilizza le API web standard.

La creazione di una piattaforma per applicazioni web fornisce svariati vantaggi sia per gli

sviluppatori di applicazioni, sia per gli utenti.

Nel seguito, per evitare confusione, si utilizzerà il termine “applicazione” per riferirsi al

software sviluppato da Mozilla (Firefox, Thunderbird, etc.) e il termine “webapp” per

riferirsi alle applicazioni web (salvo quando è ovvio a cosa ci si stia riferendo).

1.1 Vantaggi per gli utenti

1. Installazione locale e funzionamento offline: Rispetto a normali siti web, le

webapp possono in maniera più semplice essere eseguite offline.

2. Assenza di walled garden: Le webapp sono di loro natura cross-platform, gli utenti

non sono forzati ad utilizzare una singola piattaforma ma hanno libertà di scelta e

Page 5: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

5

libertà di passare da un sistema all'altro senza perdere le webapp che hanno

acquistato in precedenza.

3. Disponibilità di differenti sorgenti di distribuzione: Le API che permettono di

installare webapp permettono la presenza di più sorgenti di distribuzione che l'utente

può utilizzare. Esiste un Marketplace sviluppato da Mozilla, che però non è

avvantaggiato in alcun modo rispetto agli altri.

4. Sistema di permessi web-like che dà il pieno controllo agli utenti.

1.2 Vantaggi per gli sviluppatori

Uno degli obiettivi di questo progetto è quello di dare agli sviluppatori il pieno controllo

su tutti gli aspetti riguardanti le loro applicazioni, dalla semplicità di sviluppo fino alle

modalità di distribuzione.

1. API cross-platform: Gli sviluppatori possono creare un unico prodotto software

che può essere distribuito su tutte le piattaforme che dispongono di un moderno

browser web.

2. Accesso all'hardware: Sono state introdotte numerose nuove API per rendere le

webapp potenti quanto le applicazioni native.

3. Riutilizzare l'esperienza acquisita per lo sviluppo di siti web.

4. Userbase enorme: Le webapp possono essere eseguite su una qualsiasi piattaforma

disponga di un moderno browser web. Questo significa praticamente tutti i sistemi

operativi desktop e mobile esistenti (con alcune limitazioni in alcuni casi).

5. Libertà di distribuzione della propria applicazione: Gli sviluppatori sono liberi di

distribuire le proprie applicazioni come preferiscono. Nulla vieta la creazione di

nuove sorgenti di distribuzione (che funzionano esattamente alla pari di quelle

“ufficiali”)

Page 6: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

6

1.3 App Manifest

I metadati associati ad un'applicazione sono raccolti in un file manifest in formato JSON.

{

"version": "0.2",

"name": "Ceferino",

"description": "Ceferino, a clone of Super Pang",

"icons": {

"16": "/ceferino-16.png",

"48": "/ceferino-48.png",

"128": "/ceferino-128.png"

},

"developer": {

"name": "Marco Castelluccio",

"url": "http://marco-c.github.com/ceferinoweb/"

},

"installs_allowed_from": ["*"],

"appcache_path": "/ceferino.appcache",

"locales": {

"it": {

"description": "Ceferino, un clone di Super Pang",

"developer": {

"url": "http://marco-c.github.com/ceferinoweb/"

}

}

},

"default_locale": "en"

}

Campi del manifest:

• activities: Specifica le WebActivities che l'applicazione supporta.

• appcache_path: Specifica l'indirizzo del manifest per l'AppCache (per il supporto

allo storage offline).

• chrome: Specifica se l'applicazione deve essere eseguita con un'interfaccia di

navigazione (ad esempio, un menù di default, o i bottoni per la navigazione).

• csp: Specifica la Content Security Policy per l'applicazione.

• default_locale: Tag ([1]) che specifica il linguaggio di default dell'applicazione.

• description: Specifica la descrizione dell'applicazione.

• developer: Specifica i dati riguardanti lo sviluppatore dell'applicazione (è un

dizionario che contiene le proprietà nome e url).

• fullscreen: Specifica se l'applicazione dev'essere eseguita in modalità fullscreen.

• icons: Specifica l'insieme di icone da utilizzare per l'applicazione (è possibile

Page 7: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

7

specificare diverse icone di diverse dimensioni, così da potersi adattare a diversi

form factor).

• installs_allowed_from: Specifica i siti da cui è possibile installare l'applicazione.

• launch_path: Specifica l'indirizzo (relativo all'origine dell'applicazione) che viene

caricato al lancio della webapp.

• locales: Specifica le lingue supportate dall'applicazione. E' un dizionario che può

comprendere (e quindi sovrascrivere) gli stessi elementi presenti nell'App Manifest

(tranne default_locale, locales e installs_allowed_from).

• messages: Specifica i messaggi di sistema per i quali l'applicazione verrà notificata.

• name: Specifica il nome dell'applicazione.

• orientation: Specifica l'orientamento dell'applicazione (portrait, landscape, etc.).

• permissions: Specifica l'insieme di permessi che l'applicazione richiede.

"permissions": {

"contacts": {

"description": "Required for autocompletion in the share screen",

"access": "readcreate"

},

"alarms": {

"description": "Required to schedule notifications"

}

}

Il campo description è obbligatorio e serve per specificare il motivo per cui

l'applicazione richiede un determinato permesso.

• redirects: Nel caso di applicazioni packaged, che non sono ospitate su un server, è a

volte necessario specificare alcuni URL che vanno rediretti a pagine

dell'applicazione. Ad esempio può servire per il login con il protocollo OAuth:

"redirects": [

{"from": "http://mydomain.com/oauth2/flow.html",

"to": "/redirects/redirect.html"},

{"from": "http://mydomain.com/oauth2/dialogs_end.html",

"to": "/redirects/dialogs_end.html"}

]

I redirects sono ovviamente locali all'applicazione per questioni di sicurezza.

Page 8: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

8

• type: Specifica il tipo di applicazione, web, privileged o certified. Un diverso tipo

corrisponde a un diverso livello di privilegi (per l'accesso ad API più sensibili).

• version: Specifica la versione dell'applicazione.

Nel caso delle applicazioni hosted, l'App Manifest è servito tramite un server web (con

mimetype application/x-web-app-manifest+json, per questioni di sicurezza).

Nel caso delle applicazioni packaged, l'App Manifest è incluso nell'archivio compresso.

Esiste invece un altro manifest (Mini Manifest, per supportare installazioni/aggiornamenti)

con i seguenti campi:

• name

• package_path: Specifica l'indirizzo dell'archivio compresso che contiene

l'applicazione vera e propria.

• version

• size: Specifica la dimensione dell'archivio compresso.

• release_notes: Specifica le novità tra una versione dell'applicazione e l'altra.

• developer

• locales

• icons

I campi che compaiono sia nel Mini Manifest che nell'App Manifest devono essere uguali.

1.4 Integrazione con le diverse piattaforme

Sulle piattaforme desktop, le applicazioni vengono eseguite in maniera completamente

indipendente. Ogni applicazione ha il suo processo e viene eseguita in una o più finestre

separate.

Su Windows le applicazioni vengono installate nel menù Start e sul desktop. Possono

essere disinstallate tramite il pannello di controllo.

Page 9: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

9

Su Linux le applicazioni vengono installate nella home directory dell'utente. Vengono

utilizzati gli standard FreeDesktop (Desktop Entry Specification e Desktop Menu

Specification) per l'integrazione dell'applicazione con tutti gli ambienti desktop presenti su

Linux (GNOME, KDE, etc.).

Page 10: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

10

Su Mac le applicazioni vengono installate nella cartella /Applications, vengono

visualizzate nella dashboard e sulla barra delle applicazioni.

Su Android, le applicazioni vengono automaticamente pacchettizzate in APK e firmate

digitalmente per essere poi installate come normali applicazioni Android.

Su Firefox OS, tutte le applicazioni sono applicazioni web.

Page 11: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

11

1.5 Hosted apps

Le applicazioni hosted sono applicazioni servite tramite un normale server web. Tramite

l'App Manifest è possibile specificare i dati relativi all'applicazione.

Utilizzando determinate API (AppCache), è possibile supportare lo storage offline dei dati

dell'applicazione.

La gestione degli aggiornamenti è completamente demandata allo sviluppatore, la

piattaforma di distribuzione non ha alcun controllo sull'applicazione stessa. Per questo le

applicazioni hosted non possono accedere a determinate API che necessitano di un livello

di sicurezza particolare.

1.6 Packaged apps

Le applicazioni packaged sono applicazioni le cui risorse (codice JavaScript, HTML, CSS,

etc.) vengono incluse in un archivio compresso.

L'App Manifest che specifica i dati dell'applicazione è incluso nell'archivio ed è presente

un Mini Manifest per la gestione dell'installazione/aggiornamento della webapp.

L'aggiornamento delle applicazioni packaged può essere gestito dalla piattaforma di

distribuzione, quindi possono essere recensite e di conseguenza accedere ad API più

sensibili.

Le webapp accedono alle risorse contenute nell'archivio compresso tramite uno speciale

protocollo (“app://”).

1.7 Il sistema di sicurezza

Web: Le applicazioni di tipo web (tutte le hosted e le packaged che non richiedono

l'utilizzo di particolari API) sono applicazioni che non necessitano di particolari privilegi.

Sono trattate, dal punto di vista della sicurezza, esattamente come normale contenuto web.

Privileged: Le applicazioni di tipo privileged (solo packaged, perché per utilizzare

particolari API c'è bisogno che l'applicazione venga recensita e firmata digitalmente) sono

Page 12: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

12

applicazioni che richiedono particolari privilegi. Rispetto a normale contenuto web

godono di queste caratteristiche:

• Il codice dell'applicazione viene recensito da una piattaforma di

distribuzione.

• L'archivio compresso che contiene le risorse dell'applicazione viene firmato

digitalmente (un archivio JAR firmato con lo standard CMS/PKCS7, lo

stesso utilizzato per S/MIME).

• Possono utilizzare alcune API a cui normalmente i siti web non possono

accedere.

• Utilizza una particolare CSP (Content Security Policy) per mitigare attacchi

di code injection (per evitare che del codice estraneo possa utilizzare le API

sensibili). La politica CSP utilizzata è: default-src *; script-src 'self';

object-src 'none'; style-src 'self'

In sostanza, soltanto il codice compreso nell'archivio può essere eseguito (ad esempio, non

è possibile utilizzare la funzione “eval”, non è possibile utilizzare plugin, etc.).

E' possibile utilizzare elementi <iframe> (che però non possono accedere alle stesse API a

cui può accedere l'applicazione stessa, perché i permessi sono basati sull'origine), caricare

immagini e altri contenuti multimediali da una qualsiasi sorgente, creare connessioni di

rete tramite le API che lo supportano (XMLHttpRequest, WebSocket, TCPSocket,

WebRTC).

Per quanto riguarda i permessi, si possono verificare tre casi:

• Il permesso non viene concesso perché non era specificato nell'App

Manifest.

• Il permesso viene concesso dopo che l'utente ha esplicitamente accettato.

• Il permesso viene concesso senza chiedere all'utente. Questo è necessario

quando è difficile spiegare le implicazioni di un permesso agli utenti (ad

esempio, il permesso di utilizzare i socket).

Page 13: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

13

Come accade per i normali siti web, i permessi vengono richiesti a runtime e non all'atto

dell'installazione. Questo permette agli utenti un controllo fine-grained, perché le

applicazioni sono installabili ed eseguibili anche se non tutti i permessi vengono concessi

(al contrario di quanto avviene in altri sistemi, dove l'utente deve concedere tutti i

permessi prima di poter installare l'applicazione).

Le applicazioni vengono eseguite in processi separati e non condividono dati (compreso

cookie, dati localStorage, indexedDB e permessi).

Questo significa che uno stesso sito potrebbe essere visualizzato in maniera differente da

applicazioni differenti e che un'applicazione non può “aprirne” un'altra perché, se creasse

un elemento <iframe> che punta ad un'altra applicazione, semplicemente aprirebbe il sito

localizzato a quell'URL.

Questo approccio garantisce che le applicazioni non interagiscano tra loro in maniere

impreviste.

Nel dettaglio, a ogni Principal (che rappresenta un contesto di sicurezza) viene associato,

oltre alla semplice origine, un'ID univoco della webapp. Questo significa che tutti i

controlli di sicurezza, che vengono effettuati tramite il Principal, danno risultati diversi a

seconda che ci si trovi in un elemento che fa parte di una webapp o meno.

Page 14: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

14

Capitolo 2

Sviluppo di applicazioni

In questo capitolo si presenta alcune API interessanti per lo sviluppo di applicazioni web e

alcuni tool che semplificano la vita agli sviluppatori di questo tipo di applicazioni.

2.1 Presentazione di alcune API interessanti

2.1.1 TCPSocket API

L'API TCPSocket permette alle applicazioni privileged di creare connessioni TCP.

La definizione dell’interfaccia WebIDL è autoesplicativa:

interface TCPSocket{

readonly attribute DOMString host;

readonly attribute unsigned short port;

readonly attribute boolean ssl;

readonly attribute unsigned long bufferedAmount;

readonly attribute DOMString binaryType;

readonly attribute DOMString readyState;

TCPSocket open(DOMString host, unsigned short port, [object options]);

TCPServerSocket listen(unsigned short port, [object options, [unsigned short

backlog]])

void upgradeToSecure();

void suspend();

void resume();

void close();

boolean send(in jsval data);

attribute onopen;

attribute ondrain;

attribute ondata;

attribute onerror;

attribute onclose;

};

Page 15: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

15

Segue un estratto di codice da una webapp che supporta il download di files tramite il

protocollo BitTorrent:

connect: function() {

this._socket = navigator.mozTCPSocket.open(this.ip, this.port, { binaryType:

"arraybuffer" });

this._socket.onopen = () => {

this._connected = true;

this._socket.ondata = (event) => this.receiveData(event.data);

this._socket.onerror = (event) => console.log("onerror: " + this.ip);

this._socket.onclose = (event) => console.log("onclose: " + this.ip);

// Handshake message

let handShake = Connection.buildHandshake(this.torrent.infoHash,

myClient.peerID);

this._socket.send(handShake.buffer, handShake.byteOffset,

handShake.byteLength);

};

},

2.1.2 Geolocation API

L'API di geolocalizzazione permette alle applicazioni (senza particolari privilegi) di

accedere alla posizione dell'utente (dopo averne richiesto il permesso).

La funzione getCurrentPosition richiede in maniera asincrona la posizione e, quando la

posizione è stata acquisita, esegue una funzione di callback.

navigator.geolocation.getCurrentPosition(function(position) {

do_something(position.coords.latitude, position.coords.longitude);

});

La funzione watchPosition permette un’aquisizione continua della posizione. Funziona in

maniera simile alla getCurrentPosition. La funzione di callback viene chiamata ad

intervalli periodici, mentre la posizione sta cambiando.

var watchID = navigator.geolocation.watchPosition(function(position) {

do_something(position.coords.latitude, position.coords.longitude);

});

La funzione clearWatch permette di smettere di osservazione la posizione.

navigator.geolocation.clearWatch(watchID);

Page 16: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

16

watchPosition e getCurrentPosition permettono di specificare anche una funzione di

callback eseguita in caso di errore e un insieme di opzioni (ad esempio, l'accuracy).

function geo_success(position) {

do_something(position.coords.latitude, position.coords.longitude);

}

function geo_error() {

alert("Sorry, no position available.");

}

var geo_options = {

enableHighAccuracy: true,

maximumAge : 30000,

timeout : 27000

};

var wpid = navigator.geolocation.watchPosition(geo_success, geo_error,

geo_options);

2.1.1 Apps API

Segue un estratto del codice IDL che descrive l'interfaccia della API mozApps. Le

funzioni più importanti sono install e installPackage, che permettono di installare

un'applicazione dato l'URL al suo file manifest.

interface mozIDOMApplication : nsISupports

{

readonly attribute jsval manifest;

readonly attribute jsval updateManifest;

readonly attribute DOMString manifestURL;

readonly attribute jsval receipts; /* an array of strings */

readonly attribute DOMString origin;

readonly attribute DOMString installOrigin;

readonly attribute unsigned long long installTime;

readonly attribute boolean removable;

/**

* The current progress when downloading an offline cache.

*/

readonly attribute double progress;

/**

* The application installation state :

* "pending" : The application is being installed (eg, we're downloading the

* offline cache or the package).

* "installed" : The application is installed and ready to be launched.

* "updating" : We are updating the offline-cache or the package.

*/

readonly attribute DOMString installState;

/**

* fires a nsIDOMApplicationEvent when a change in appcache download or

* package download happens.

*/

attribute nsIDOMEventListener onprogress;

/**

Page 17: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

17

* The date of the last update check.

*/

readonly attribute unsigned long long lastUpdateCheck;

/**

* The date of the last updated manifest.

*/

readonly attribute unsigned long long updateTime;

/**

* Starts the process of looking for an update.

*/

nsIDOMDOMRequest checkForUpdate();

readonly attribute boolean downloadAvailable;

readonly attribute boolean downloading;

readonly attribute boolean readyToApplyDownload;

readonly attribute long downloadSize;

// This is a DOMError

readonly attribute nsISupports downloadError;

attribute nsIDOMEventListener ondownloadsuccess;

attribute nsIDOMEventListener ondownloaderror;

attribute nsIDOMEventListener ondownloadavailable;

/**

* Will fire once the mgmt.applyDownload() call succeeds.

*/

attribute nsIDOMEventListener ondownloadapplied;

/**

* Starts to download an update. If |downloading| is true, this

* is a no-op.

*/

void download();

/**

* Cancels an ongoing update download.

*/

void cancelDownload();

/* startPoint will be used when several launch_path exists for an app */

nsIDOMDOMRequest launch([optional] in DOMString startPoint);

/**

* Clear data that has been collected through mozbrowser elements.

* onsuccess will be called once data is actually cleared.

*/

nsIDOMDOMRequest clearBrowserData();

/**

* Inter-App Communication APIs.

*

* https://wiki.mozilla.org/WebAPI/Inter_App_Communication_Alt_proposal

*/

nsISupports connect(in DOMString keyword,

[optional] in jsval rules); // nsISupports is a Promise.

nsISupports getConnections(); // nsISupports is a Promise.

};

interface mozIDOMApplicationMgmt : nsISupports

{

/**

* the request will return the all the applications installed. Only accessible

* to privileged callers.

*/

Page 18: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

18

nsIDOMDOMRequest getAll();

/**

* the request will return the applications acquired from all origins but

* which are not launchable (e.g. by not being natively installed), or null.

*/

nsIDOMDOMRequest getNotInstalled();

/**

* event listener to get notified of application installs. Only settable by

* privileged callers.

* the event will be a mozIDOMApplicationEvent

*/

attribute nsIDOMEventListener oninstall;

/**

* event listener to get notified of application uninstalls. Only settable by

* privileged callers.

* the event will be a mozIDOMApplicationEvent

*/

attribute nsIDOMEventListener onuninstall;

/**

* Applies a downloaded update.

* This function is a no-op if it's passed an app object which doesn't have

* |readyToApplyDownload| set to true.

*/

void applyDownload(in mozIDOMApplication app);

/**

* Uninstall a web app.

*

* @param app : the app object of the web app to be uninstalled.

* @returns : A DOMRequest object, returning the app's origin in |result|

* if uninstall succeeds; returning "NOT_INSTALLED" error

otherwise.

*/

nsIDOMDOMRequest uninstall(in mozIDOMApplication app);

};

interface mozIDOMApplicationRegistry : nsISupports

{

/**

* Install a web app.

*

* @param manifestUrl : the URL of the webapps manifest.

* @param parameters : A structure with optional information.

* {

* receipts: ... Will be used to specify the payment

receipts for this installation.

* categories: ... Will be used to specify the

categories of the webapp.

* }

* @returns : A DOMRequest object, returning the app object in

|result| if install succeeds.

*/

nsIDOMDOMRequest install(in DOMString manifestUrl, [optional] in jsval

parameters);

/**

* the request will return the application currently installed, or null.

*/

nsIDOMDOMRequest getSelf();

/**

* the request will return the application if the app from that origin is

installed

*/

Page 19: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

19

nsIDOMDOMRequest checkInstalled(in DOMString manifestUrl);

/**

* the request will return the applications installed from this origin, or

null.

*/

nsIDOMDOMRequest getInstalled();

/**

* Install a packaged web app.

*

* @param packageUrl : the URL of the webapps manifest.

* @param parameters : A structure with optional information.

* {

* receipts: ... Will be used to specify the payment

receipts for this installation.

* categories: ... Will be used to specify the

categories of the webapp.

* }

* @returns : A DOMRequest object, returning the app object in

|result| if install succeeds.

*/

nsIDOMDOMRequest installPackage(in DOMString packageUrl, [optional] in jsval

parameters);

readonly attribute mozIDOMApplicationMgmt mgmt;

};

2.1.4 Indexed Database API

IndexedDB è un'API che permette lo storage di una larga quantità di dati in maniera

offline.

• I dati sono salvati in coppie chiave-valore. I valori possono essere oggetti

qualsiasi e la chiave può essere una qualsiasi delle proprietà di questi oggetti.

• Tutte le operazioni sono eseguite all'interno di una transazione. Questo

garantisce l'atomicità anche nel caso l'utente apra due pagine dello stesso

sito.

• L'API è asincrona. Come le altre API del genere, ci sono dei callback che

vengono eseguiti quando le operazioni sul database sono terminate.

• Non è una database relazionale, ma object-oriented. E' un database NoSQL,

non utilizza SQL.

• Ogni origine (e quindi ogni webapp) ha il suo insieme di basi di dati,

separato dagli altri.

Page 20: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

20

2.1.5 Payments API

interface nsINavigatorPayment : nsISupports

{

// The 'jwts' parameter can be either a single DOMString or an array of

// DOMStrings. In both cases, it represents the base64url encoded and

// digitally signed payment information. Each payment provider should

// define its supported JWT format.

nsIDOMDOMRequest pay(in jsval jwts);

};

Il formato JWT (JSON Web Token) è utilizzato per rappresentare le “ricevute”.

Le ricevute sono codificate in un oggetto JSON che viene poi firmato digitalmente

utilizzando lo standard JWS (JSON Web Signature) e criptate utilizzando lo standard JWE

(JSON Web Encryption).

Segue un esempio di oggetto JSON che specifica una “ricevuta”:

{

"iss": APPLICATION_KEY,

"aud": "marketplace.firefox.com",

...

"request": {

"name": "Magical Unicorn",

"pricePoint": 1,

"postbackURL": "https://yourapp.com/postback",

"chargebackURL": "https://yourapp.com/chargeback"

}

}

Lo sviluppatore deve occuparsi di creare (e firmare digitalmente) dei file JWT per ogni

prodotto che vende. Un sito di terze parti (specificato nel capo “aud”) si occuperà del

pagamento vero e proprio e, una volta che il pagamento sarà stato effettuato, notificherà

l'avvenuto acquisto all'indirizzo specificato in “request.postbackURL”.

var request = navigator.mozPay([signedJWT]);

request.onsuccess = function() {

// Attende che arrivi la notifica dal server dei pagamenti.

};

request.onerror = function() {

console.log('navigator.mozPay() error: ' + this.error.name);

}

2.1.6 WebRTC

WebRTC (Web Real-Time Communication) è un'insieme di API che permette lo sviluppo

Page 21: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

21

di applicazioni multimediali che comunicano in maniera P2P (senza l'utilizzo di plugin di

terze parti).

Tra le altre sono presenti le seguenti API:

getUserMedia – Permette di accedere ai dispositivi multimediali dell'utente (microfono,

videocamera, etc.).

MediaStream – Permette di creare e manipolare stream multimediali

Sono inoltre presenti API per creare connessioni P2P e condividere dati o stream

multimediali.

2.1.7 WebGL, Fullscreen API, Pointer Lock API, Gamepad API, WebAudio

API

Uno degli ambiti applicativi più interessanti per le applicazioni web è quello dei giochi.

WebGL – Quest'API permette il rendering di grafica 3D in un elemento <canvas> tramite

la GPU e senza l'utilizzo di plugin. E' molto simile a OpenGL ES 2.0 (e infatti entrambi gli

standard sono mantenuti dal Khronos Group).

FullScreen API - Quest'API permette alle applicazioni web di essere eseguite in modalità

fullscreen. L'API permette di effettuare il rendering in fullscreen di un elemento (e

eventualmente i suoi figli), eliminando dallo schermo l'interfaccia utente del browser e

delle altre applicazioni.

Si utilizza in maniera molto semplice tramite la funzione requestFullscreen di un elemento

del DOM.

PointerLock API – Quest'API fornisce la possibilità di accedere ai movimenti del mouse

in maniera dettagliata, di accedere agli eventi del mouse anche quando raggiunge i lati del

browser o dello schermo, di eliminare il cursore dallo schermo.

Pur non sembrando un'API così importante, è in realtà fondamentale per i giochi e per i

Page 22: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

22

software di modellazione 3D.

Si utilizza in maniera simile alla FullScreen API, tramite la funzione requestPointerLock

di un elemento del DOM.

La Gamepad API fornisce un'interfaccia per i controller gamepad, la WebAudio API

permette di creare, manipolare e riprodurre risorse audio su una pagina web (in maniera

molto più dettagliata rispetto a quanto era possibile fare prima).

2.2 Presentazione di alcuni tool di sviluppo interessanti

2.2.1 Remote Debugger

Il debugger remoto permette di utilizzare alcuni dei tool di sviluppo web presenti in

Firefox con una webapp (profiling del codice, profiling delle risorse di rete utilizzate,

inspector, debugger vero e proprio, console, etc.).

Il WebRT, che si occupa di lanciare la webapp, implementa un DebuggerServer a cui dei

DebuggerClient possono connettersi tramite socket TCP. La soluzione è molto flessibile

perché il DebuggerServer e il DebuggerClient possono ovviamente anche risiedere su

macchine diverse.

Page 23: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

23

2.2.2 Emscripten

Emscripten è un compilatore che trasforma bytecode LLVM in codice JavaScript. Il

bytecode LLVM può essere generato da vari linguaggi, in particolare da C/C++ usando

Clang.

In questa maniera si può compilare un software già esistente scritto in C/C++ in JavaScript

ed eseguirlo in un browser web.

Ovviamente è anche possibile compilare degli interpreti scritti in C/C++ (ad esempio,

CPython), e quindi eseguirli sul web (ad esempio, interpretare codice Python in una pagina

web).

Recentemente è stato anche definito un subset di JavaScript (asm.js) che rappresenta il

target di Emscripten e che può essere compilato ahead-of-time garantendo performance

molto vicine a quelle del C/C++.

Page 24: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

24

Capitolo 3

Il desktop WebRuntime (WebRT)

Il supporto alle Open Web Apps sulle piattaforme desktop comprende:

Il codice per l'installazione delle webapp e la loro integrazione col sistema operativo, che è

incluso nel browser.

Il software eseguibile che permette di lanciare le webapp e che fornisce API per

l'integrazione col sistema operativo, indipendente dal browser stesso.

3.1 Installazione

Il codice relativo all'installazione è diviso in due parti. Una parte, cross-platform,

implementa l'API mozApps, l'altra implementa l'installazione vera e propria ed è differente

per ogni sistema.

L'implementazione cross-platform dell'API mozApps si occupa di gestire un registro delle

webapp installate e di fornire, appunto, le funzioni mozApps viste in precedenza.

E' inoltre presente un “protocol handler” che gestisce il protocollo app://, che permette ad

applicazioni packaged di accedere alle proprie risorse dall'archivio compresso.

L'installazione provvede a creare i file necessari per l'esecuzione delle webapp e per

l'integrazione della stessa nei meccanismi di gestione software propri della piattaforma

sottostante.

Page 25: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

25

Su Windows, i dati sono salvati in una cartella locale ad ogni utente e nel registro di

sistema (per l'integrazione col pannello di controllo). Vengono creati due collegamenti sul

desktop e nel menu di start. Viene fornito un software per la disinstallazione (creato

tramite NSIS) come tipico per le applicazioni Windows.

Su Mac, i dati sono salvati nella cartella /Applications. Nella cartella d'installazione è

presente un file di descrizione del bundle, che Mac utilizza per registrare l'applicazione nel

sistema.

Su Linux, i dati sono salvati nella home dell'utente. Si utilizzano gli standard definiti da

FreeDesktop.org per fornire l'integrazione dell'applicazione con tutti i Desktop

Environment conformi agli standard (GNOME, KDE, etc.).

I file creati nella cartella d'installazione sono i seguenti:

• webapp.ini – Comprende alcuni dati per il WebRT (ad esempio, dove trovare la

libreria libxul)

• webapp.json – Comprende alcuni dati riguardanti la webapp, come il suo App

Manifest e il profilo da cui è stata installata.

• L'eseguibile che si occupa di lanciare la webapp.

• Directory del profilo – Directory che contiene i dati dell'applicazione (AppCache,

cache, IndexedDB, permessi granted dall'utente, etc.). L'AppCache viene precaricata

all'atto dell'installazione, se specificato nell'App Manifest (questo permette alla

webapp di essere eseguita offline).

• L'icona per la webapp.

L'installazione dell'applicazione viene eseguita tramite il browser o il WebRT (quando

vengono utilizzate le chiamate install o installPackage dell'API mozApps):

Page 26: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

26

A titolo di esempio, si mostra una parte dell'implementazione dell'installazione per Linux

(e BSD):

LinuxNativeApp.prototype = {

__proto__: NativeApp.prototype,

install: function(aZipPath) {

return Task.spawn(function() {

this._getInstallDir();

try {

this._createDirectoryStructure();

this._copyPrebuiltFiles();

this._createConfigFiles();

if (aZipPath) {

yield OS.File.move(aZipPath, OS.Path.join(this.tmpInstallDir,

"application.zip"));

}

yield this.getIcon();

// Remove previously installed app (for update purposes)

this._removeInstallation(true);

} catch (ex) {

removeFiles([this.tmpInstallDir]);

throw(ex);

}

try {

yield moveDirectory(this.tmpInstallDir, this.installDir);

this._createSystemFiles();

} catch (ex) {

this._removeInstallation(false);

throw(ex);

}

}.bind(this));

},

3.2 Architettura del WebRT

Il webruntime è un semplice eseguibile che utilizza le librerie dinamiche del browser

engine (Gecko) per fornire una shell XUL in cui lanciare le applicazioni.

Page 27: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

27

Gecko – Gecko è il sottosistema che contiene il browser engine e il rendering engine.

Gecko si occupa del rendering del contenuto web. Il rendering engine si occupa anche del

rendering di interfacce utente definite tramite XUL.

Il browser engine è un'interfaccia ad alto livello per il rendering engine.

XPCOM (Cross Platform Component Object Model) – Fornisce le funzionalità per creare

applicazioni modulari in maniera cross-platform (è simile a Microsoft COM). Gestisce il

passaggio di parametri tra differenti componenti, la gestione della memoria, etc.

XPConnect è un “ponte” tra componenti scritti in JavaScript e componenti scritti in C++.

NSPR (Netscape Portable Runtime) – E' una libreria che fornisce un insieme di API

system-level e cross-platform (ad esempio le primitive per il locking e alcune funzioni

simili a quelle presenti in libc).

Toolkit – Un insieme di servizi cross-platform (gestione degli aggiornamenti, gestione dei

profili, etc.). Nel Toolkit è presente anche il codice per l'installazione delle webapp.

XUL (XML User Interface Language) è un linguaggio XML per definire interfacce

grafiche. Non è uno standard, ma è un linguaggio utilizzato internamente dai progetti

Page 28: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

28

basati sulla piattaforma Mozilla. XUL viene utilizzato nel WebRT per definire l'interfaccia

(la finestra, i menù, etc.) della shell che contiene l'applicazione web (non viene utilizzato

in alcun modo dalle applicazioni stesse).

Firefox, Thunderbird e tutti gli altri prodotti Mozilla (compreso il WebRT) sono tutte

applicazioni che fanno uso dell'engine Gecko.

Il WebRT non dipende da Firefox, ma dalle librerie condivise di Gecko (libxul, il nome

della libreria è misleading perché in realtà fa molto più che semplicemente effettuare il

parsing di file XUL).

3.3 Funzionamento del WebRT

In questa sezione si presentano alcune parti dell'implementazione del WebRT,

volutamente semplificate e con alcuni commenti esplicativi in più.

Segue un estratto di codice dell'eseguibile principale del WebRT, che non fa altro che

caricare la libreria libxul dalla directory d'installazione e poi, dopo alcuni passi di

inizializzazione, caricare la shell XUL e lanciare la webapp.

bool GRELoadAndLaunch(const char* firefoxDir)

{

char xpcomDllPath[MAXPATHLEN];

snprintf(xpcomDllPath, MAXPATHLEN, "%s/%s", firefoxDir, XPCOM_DLL);

if (NS_FAILED(XPCOMGlueStartup(xpcomDllPath))) {

ErrorDialog("Couldn't load the XPCOM library");

return false;

}

if (NS_FAILED(XPCOMGlueLoadXULFunctions(kXULFuncs))) {

ErrorDialog("Couldn't load libxul");

return false;

}

// NOTE: The GRE has successfully loaded, so we can use XPCOM now

{ // Scope for any XPCOM stuff we create

ScopedLogging log;

// Get the path to the runtime

char rtPath[MAXPATHLEN];

snprintf(rtPath, MAXPATHLEN, "%s/%s", firefoxDir, kWEBAPPRT_PATH);

// Get the path to the runtime's INI file

char rtIniPath[MAXPATHLEN];

snprintf(rtIniPath, MAXPATHLEN, "%s/%s", rtPath, kWEBAPPRT_INI);

Page 29: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

29

// Load the runtime's INI from its path

nsCOMPtr<nsIFile> rtINI;

if (NS_FAILED(XRE_GetFileFromPath(rtIniPath, getter_AddRefs(rtINI)))) {

ErrorDialog("Couldn't load the runtime INI");

return false;

}

bool exists;

nsresult rv = rtINI->Exists(&exists);

if (NS_FAILED(rv) || !exists) {

ErrorDialog("The runtime INI doesn't exist");

return false;

}

nsXREAppData *webShellAppData;

if (NS_FAILED(XRE_CreateAppData(rtINI, &webShellAppData))) {

ErrorDialog("Couldn't read WebappRT application.ini");

return false;

}

SetAllocatedString(webShellAppData->profile, profile);

// nsXREAppData::name is used for the class name part of the WM_CLASS

// property. Set it so that the DE can match our window to the correct

// launcher.

char programClass[MAXPATHLEN];

snprintf(programClass, MAXPATHLEN, "owa-%s", profile);

SetAllocatedString(webShellAppData->name, programClass);

nsCOMPtr<nsIFile> directory;

if (NS_FAILED(XRE_GetFileFromPath(rtPath, getter_AddRefs(directory)))) {

ErrorDialog("Couldn't open runtime directory");

return false;

}

nsCOMPtr<nsIFile> xreDir;

if (NS_FAILED(XRE_GetFileFromPath(firefoxDir, getter_AddRefs(xreDir)))) {

ErrorDialog("Couldn't open XRE directory");

return false;

}

xreDir.forget(&webShellAppData->xreDirectory);

NS_IF_RELEASE(webShellAppData->directory);

directory.forget(&webShellAppData->directory);

XRE_main(*pargc, *pargv, webShellAppData, 0);

XRE_FreeAppData(webShellAppData);

}

return true;

}

void CopyAndRelaunch(const char* firefoxDir, const char* curExePath)

{

char newExePath[MAXPATHLEN];

snprintf(newExePath, MAXPATHLEN, "%s/%s", firefoxDir, kAPP_RT);

if (unlink(curExePath) == -1) {

ErrorDialog("Couldn't remove the old webapprt-stub executable");

return;

}

if (!CopyFile(newExePath, curExePath)) {

ErrorDialog("Couldn't copy the new webapprt-stub executable");

return;

}

Page 30: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

30

execv(curExePath, *pargv);

ErrorDialog("Couldn't execute the new webapprt-stub executable");

}

void RemoveApplication(nsINIParser& parser, const char* curExeDir, const char*

profile) {

if (!isProfileOverridden) {

// Remove the desktop entry file.

char desktopEntryFilePath[MAXPATHLEN];

char* dataDir = getenv("XDG_DATA_HOME");

if (dataDir && *dataDir) {

snprintf(desktopEntryFilePath, MAXPATHLEN, "%s/applications/owa-

%s.desktop", dataDir, profile);

} else {

char* home = getenv("HOME");

snprintf(desktopEntryFilePath, MAXPATHLEN,

"%s/.local/share/applications/owa-%s.desktop", home, profile);

}

unlink(desktopEntryFilePath);

}

// Remove the files from the installation directory.

char webAppIniPath[MAXPATHLEN];

snprintf(webAppIniPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_INI);

unlink(webAppIniPath);

char curExePath[MAXPATHLEN];

snprintf(curExePath, MAXPATHLEN, "%s/%s", curExeDir, kAPP_RT);

unlink(curExePath);

char webAppJsonPath[MAXPATHLEN];

snprintf(webAppJsonPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_JSON);

unlink(webAppJsonPath);

char iconPath[MAXPATHLEN];

snprintf(iconPath, MAXPATHLEN, "%s/icon.png", curExeDir);

unlink(iconPath);

char appName[MAXPATHLEN];

if (NS_FAILED(parser.GetString("Webapp", "Name", appName, MAXPATHLEN))) {

strcpy(appName, profile);

}

char uninstallMsg[MAXPATHLEN];

if (NS_SUCCEEDED(parser.GetString("Webapp", "UninstallMsg", uninstallMsg,

MAXPATHLEN))) {

/**

* The only difference between libnotify.so.4 and libnotify.so.1 for these

symbols

* is that notify_notification_new takes three arguments in libnotify.so.4

and

* four in libnotify.so.1.

* Passing the fourth argument as nullptr is binary compatible.

*/

typedef void (*notify_init_t)(const char*);

typedef void* (*notify_notification_new_t)(const char*, const char*, const

char*, const char*);

typedef void (*notify_notification_show_t)(void*, void**);

void *handle = dlopen("libnotify.so.4", RTLD_LAZY);

if (!handle) {

handle = dlopen("libnotify.so.1", RTLD_LAZY);

if (!handle)

return;

Page 31: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

31

}

notify_init_t nn_init = (notify_init_t)(uintptr_t)dlsym(handle,

"notify_init");

notify_notification_new_t nn_new =

(notify_notification_new_t)(uintptr_t)dlsym(handle, "notify_notification_new");

notify_notification_show_t nn_show =

(notify_notification_show_t)(uintptr_t)dlsym(handle,

"notify_notification_show");

if (!nn_init || !nn_new || !nn_show) {

dlclose(handle);

return;

}

nn_init(appName);

void* n = nn_new(uninstallMsg, nullptr, "dialog-information", nullptr);

nn_show(n, nullptr);

dlclose(handle);

}

}

int main(int argc, char *argv[])

{

pargc = &argc;

pargv = &argv;

// Get current executable path

char curExePath[MAXPATHLEN];

if (NS_FAILED(mozilla::BinaryPath::Get(argv[0], curExePath))) {

ErrorDialog("Couldn't read current executable path");

return 255;

}

char curExeDir[MAXPATHLEN];

GetDirFromPath(curExeDir, curExePath);

bool removeApp = false;

for (int i = 1; i < argc; i++) {

if (!strcmp(argv[i], "-remove")) {

removeApp = true;

}

}

char firefoxDir[MAXPATHLEN];

// Check if Firefox is in the same directory as the webapp runtime.

// This is the case for webapprt chrome and content tests.

if (GRELoadAndLaunch(curExeDir, true)) {

return 0;

}

// Set up webAppIniPath with path to webapp.ini

char webAppIniPath[MAXPATHLEN];

snprintf(webAppIniPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_INI);

// Open webapp.ini as an INI file

nsINIParser parser;

if (NS_FAILED(parser.Init(webAppIniPath))) {

ErrorDialog("Couldn't open webapp.ini");

return 255;

}

// Set up our environment to know where webapp.ini was loaded from

if (setenv(kAPP_ENV_VAR, webAppIniPath, 1) == -1) {

ErrorDialog("Couldn't set up app environment");

return 255;

Page 32: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

32

}

// Get profile dir from webapp.ini

if (NS_FAILED(parser.GetString("Webapp", "Profile", profile, MAXPATHLEN))) {

ErrorDialog("Couldn't retrieve profile from web app INI file");

return 255;

}

if (removeApp) {

RemoveApplication(parser, curExeDir, profile);

return 0;

}

// Get the location of Firefox from our webapp.ini

if (NS_FAILED(parser.GetString("WebappRT", "InstallDir", firefoxDir,

MAXPATHLEN))) {

ErrorDialog("Couldn't find your Firefox install directory.");

return 255;

}

// Set up appIniPath with path to application.ini.

// This is in the Firefox installation directory.

char appIniPath[MAXPATHLEN];

snprintf(appIniPath, MAXPATHLEN, "%s/%s", firefoxDir, kAPP_INI);

if (NS_FAILED(parser.Init(appIniPath))) {

return 255;

}

// Get buildid of Firefox we're trying to load (MAXPATHLEN only for

convenience)

char buildid[MAXPATHLEN];

if (NS_FAILED(parser.GetString("App", "BuildID", buildid, MAXPATHLEN))) {

ErrorDialog("Couldn't read BuildID from Firefox application.ini");

return 255;

}

// If WebAppRT version == Firefox version, load XUL and execute the

application

if (!strcmp(buildid, NS_STRINGIFY(GRE_BUILDID))) {

if (GRELoadAndLaunch(firefoxDir, false))

return 0;

}

// Else, copy WebAppRT from Firefox installation and re-execute the process

else

CopyAndRelaunch(firefoxDir, curExePath);

return 255;

}

Segue un estratto del codice XUL e del codice JavaScript che definiscono l'interfaccia

della finestra principale del WebRT. La webapp viene caricata nell'elemento XUL

<browser> (che si comporta in maniera molto simile ad un elemento <iframe>, con alcune

proprietà e funzioni in più).

webapp.xul: <?xml version="1.0"?>

<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

Page 33: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

33

<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>

<!DOCTYPE window [

<!ENTITY % webappDTD SYSTEM "chrome://webapprt/locale/webapp.dtd">

%webappDTD;

]>

<window windowtype="webapprt:webapp"

id="default"

xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"

width="1024" height="768"

fullscreenbutton="true"

persist="screenX screenY width height sizemode"

>

<script type="application/javascript"

src="chrome://global/content/globalOverlay.js"/>

<script type="application/javascript"

src="chrome://webapprt/content/webapp.js"/>

<commandset id="mainCommandSet">

...

</commandset>

<keyset id="mainKeyset">

...

</keyset>

<menubar id="main-menubar">

<menu id="file-menu" label="&fileMenu.label;"

accesskey="&fileMenu.accesskey;">

<menupopup id="menu_FilePopup">

<menuitem id="menu_FileQuitItem"

label="&quitApplicationCmd.label;"

accesskey="&quitApplicationCmd.accesskey;"

key="key_quitApplication"

command="cmd_quitApplication"/>

</menupopup>

</menu>

<menu id="edit-menu" label="&editMenu.label;"

accesskey="&editMenu.accesskey;">

<menupopup id="menu_EditPopup"

onpopupshowing="updateEditUIVisibility()"

onpopuphidden="updateEditUIVisibility()">

<menuitem id="menu_undo"

label="&undoCmd.label;"

key="key_undo"

accesskey="&undoCmd.accesskey;"

command="cmd_undo"/>

...

</menupopup>

</menu>

</menubar>

<browser type="content-primary" id="content" flex="1"

context="contentAreaContextMenu" />

<popupset>

<menupopup id="contentAreaContextMenu" pagemenu="start"

onpopupshowing="return showContextMenu(event, this)"

onpopuphiding="hideContextMenu(event, this)">

</menupopup>

</popupset>

</window>

Page 34: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

34

webapp.js: const Cc = Components.classes;

const Ci = Components.interfaces;

const Cu = Components.utils;

Cu.import("resource://webapprt/modules/WebappRT.jsm");

Cu.import("resource://gre/modules/Services.jsm");

Cu.import("resource://gre/modules/XPCOMUtils.jsm");

XPCOMUtils.defineLazyGetter(this, "gAppBrowser",

function() document.getElementById("content"));

#ifdef MOZ_CRASHREPORTER

XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",

"@mozilla.org/toolkit/crash-reporter;1",

"nsICrashReporter");

#endif

let progressListener = {

QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,

Ci.nsISupportsWeakReference]),

onLocationChange: function onLocationChange(progress, request, location,

flags) {

// Set the title of the window to the name of the webapp, adding the origin

// of the page being loaded if it's from a different origin than the app

// (per security bug 741955, which specifies that other-origin pages loaded

// in runtime windows must be identified in chrome).

let title = WebappRT.config.app.manifest.name;

let origin = location.prePath;

if (origin != WebappRT.config.app.origin) {

title = origin + " - " + title;

// We should exit fullscreen mode if the user navigates off the app

// origin.

document.mozCancelFullScreen();

}

document.documentElement.setAttribute("title", title);

},

onStateChange: function onStateChange(aProgress, aRequest, aFlags, aStatus) {

if (aRequest instanceof Ci.nsIChannel &&

aFlags & Ci.nsIWebProgressListener.STATE_START &&

aFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) {

updateCrashReportURL(aRequest.URI);

}

}

};

function onLoad() {

window.removeEventListener("load", onLoad, false);

gAppBrowser.addProgressListener(progressListener,

Ci.nsIWebProgress.NOTIFY_LOCATION |

Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);

updateMenuItems();

// Listen for clicks to redirect <a target="_blank"> to the browser.

// This doesn't capture clicks so content can capture them itself and do

// something different if it doesn't want the default behavior.

gAppBrowser.addEventListener("click", onContentClick, false, true);

if (WebappRT.config.app.manifest.fullscreen) {

enterFullScreen();

}

Page 35: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

35

}

window.addEventListener("load", onLoad, false);

function onUnload() {

gAppBrowser.removeProgressListener(progressListener);

}

window.addEventListener("unload", onUnload, false);

// Fullscreen handling.

function enterFullScreen() {

// We call mozRequestFullScreen here so that the app window goes in

// fullscreen mode as soon as it's loaded and not after the <browser>

// content is loaded.

gAppBrowser.mozRequestFullScreen();

// We need to call mozRequestFullScreen on the document element too,

// otherwise the app isn't aware of the fullscreen status.

gAppBrowser.addEventListener("load", function onLoad() {

gAppBrowser.removeEventListener("load", onLoad, true);

gAppBrowser.contentDocument.

documentElement.wrappedJSObject.mozRequestFullScreen();

}, true);

}

#ifndef XP_MACOSX

document.addEventListener('mozfullscreenchange', function() {

if (document.mozFullScreenElement) {

document.getElementById("main-menubar").style.display = "none";

} else {

document.getElementById("main-menubar").style.display = "";

}

}, false);

#endif

/**

* Direct a click on <a target="_blank"> to the user's default browser.

*

* In the long run, it might be cleaner to move this to an extension of

* nsIWebBrowserChrome3::onBeforeLinkTraversal.

*

* @param {DOMEvent} event the DOM event

**/

function onContentClick(event) {

let target = event.target;

if (!(target instanceof HTMLAnchorElement) ||

target.getAttribute("target") != "_blank") {

return;

}

let uri = Services.io.newURI(target.href,

target.ownerDocument.characterSet,

null);

// Direct the URL to the browser.

Cc["@mozilla.org/uriloader/external-protocol-service;1"].

getService(Ci.nsIExternalProtocolService).

getProtocolHandlerInfo(uri.scheme).

launchWithURI(uri);

// Prevent the runtime from loading the URL. We do this after directing it

// to the browser to give the runtime a shot at handling the URL if we fail

// to direct it to the browser for some reason.

event.preventDefault();

}

function updateCrashReportURL(aURI) {

Page 36: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

36

#ifdef MOZ_CRASHREPORTER

if (!gCrashReporter.enabled)

return;

let uri = aURI.clone();

// uri.userPass throws on protocols without the concept of authentication,

// like about:, which tests can load, so we catch and ignore an exception.

try {

if (uri.userPass != "") {

uri.userPass = "";

}

} catch (e) {}

gCrashReporter.annotateCrashReport("URL", uri.spec);

#endif

}

// Context menu handling code.

// At the moment there isn't any built-in menu, we only support HTML5 custom

// menus.

let gContextMenu = null;

XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {

let tmp = {};

Cu.import("resource://gre/modules/PageMenu.jsm", tmp);

return new tmp.PageMenu();

});

function showContextMenu(aEvent, aXULMenu) {

if (aEvent.target != aXULMenu) {

return true;

}

gContextMenu = new nsContextMenu(aXULMenu);

if (gContextMenu.shouldDisplay) {

updateEditUIVisibility();

}

return gContextMenu.shouldDisplay;

}

function hideContextMenu(aEvent, aXULMenu) {

if (aEvent.target != aXULMenu) {

return;

}

gContextMenu = null;

updateEditUIVisibility();

}

function nsContextMenu(aXULMenu) {

this.initMenu(aXULMenu);

}

nsContextMenu.prototype = {

initMenu: function(aXULMenu) {

this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(document.popupNode,

aXULMenu);

this.shouldDisplay = this.hasPageMenu;

},

};

Page 37: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

37

Bibliografia

[1] Tags for Identifying Languages - http://www.ietf.org/rfc/rfc4646.txt

[2] Desktop Menu Specification - http://standards.freedesktop.org/menu-spec/menu-spec-

latest.html

[3] Desktop Entry Specification - http://standards.freedesktop.org/desktop-entry-

spec/latest/

[4] Content Security Policy 1.1 - https://dvcs.w3.org/hg/content-security-policy/raw-

file/tip/csp-specification.dev.html

[5] AppCache - http://www.w3.org/TR/offline-webapps/ e

http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#appcache

[6] CMS (Cryptographic Message Syntax) - http://tools.ietf.org/html/rfc5652I

[7] JAR File Specification -

http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Signed_JAR_File

[8] Raw Socket API - http://www.w3.org/2012/sysapps/raw-sockets/

[9] Geolocation API - http://www.w3.org/TR/geolocation-API/

[10] XUL documentation - https://developer.mozilla.org/en-US/docs/XUL

[11] XPCOM documentation - https://developer.mozilla.org/en/docs/XPCOM

[12] A case study in architectural analysis: The evolution of the modern web browser -

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.68.52

[13] JWT (JSON Web Token) - http://openid.net/specs/draft-jones-json-web-token-

07.html

[14] Indexed Database API - http://www.w3.org/TR/IndexedDB/

[15] Interface DOMError - http://www.w3.org/TR/dom/#interface-domerror

Page 38: Sviluppo di applicazioni Open Web Apps multipiattaforma · Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica ... Uno degli obiettivi di questo progetto è quello di

Sviluppo di applicazioni Open Web Apps multipiattaforma

38

[16] WebRTC 1.0: Real-time Communication Between Browsers -

http://dev.w3.org/2011/webrtc/editor/webrtc.html

[17] WebGL (OpenGL ES 2.0 for the Web) - http://www.khronos.org/webgl/

[18] Fullscreen - https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#api

[19] Pointer Lock - https://dvcs.w3.org/hg/pointerlock/raw-file/default/index.html

[20] Gamepad - https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html

[21] Web Audio API - https://dvcs.w3.org/hg/audio/raw-

file/tip/webaudio/specification.html

[22] Emscripten: An LLVM-to-JavaScript Compiler -

https://github.com/kripken/emscripten/blob/master/docs/paper.pdf?raw=true

[23] Gecko security model - https://developer.mozilla.org/en-

US/docs/Security_check_basics

[24] nsIPrincipal interface - https://developer.mozilla.org/en-

US/docs/XPCOM_Interface_Reference/nsIPrincipal

[25] XPIDL - https://developer.mozilla.org/en-US/docs/Mozilla/XPIDL

[26] The Web Origin Concept - http://www.ietf.org/rfc/rfc6454.txt

[27] T. Berners-Lee; R. Fielding; L. Masinter. Uniform Resource Identifiers (URI):

generic syntax. January 2005. Internet RFC 3986. URL:

http://www.ietf.org/rfc/rfc3986.txt

[28] The application/json Media Type for JavaScript Object Notation (JSON) -

http://www.ietf.org/rfc/rfc4627.txt

[29] Il termine “plugin” e l’elemento <iframe> sono descritti nella specifica HTML5 -

http://www.w3.org/TR/html5/

[30] The XMLHttpRequest Object - http://www.w3.org/TR/2008/WD-XMLHttpRequest-

20080415/

Tutto il codice incluso in questa trattazione è rilasciato sotto i termini della licenza MPL

(Mozilla Public License) 2.0. E’ possibile ottenerne una copia da

http://mozilla.org/MPL/2.0/.