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:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
24
gaia/dev_apps/contacts-ds-provider2/index.html
Executable file
24
gaia/dev_apps/contacts-ds-provider2/index.html
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<title>Provider 2</title>
|
||||
<script defer src="/js/linkedin.js"></script>
|
||||
<script defer src="/js/app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<section>
|
||||
<header>
|
||||
<h1>Linked In contacts provider</h1>
|
||||
</header>
|
||||
<article>
|
||||
This test app will allow you to log in into your linked in account and store your contacts into an 'contacts' datastore.
|
||||
</article>
|
||||
</section>
|
||||
<section id="info"></section>
|
||||
<section id="commands">
|
||||
<button id="fillDS">Fill DataStore</button>
|
||||
<button id="resetDS">Clean DataStore</button>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
85
gaia/dev_apps/contacts-ds-provider2/js/app.js
Executable file
85
gaia/dev_apps/contacts-ds-provider2/js/app.js
Executable file
|
|
@ -0,0 +1,85 @@
|
|||
'use strict';
|
||||
|
||||
var App = function App() {
|
||||
|
||||
var store = null;
|
||||
var info = null;
|
||||
var fillButton, resetButton;
|
||||
|
||||
var DS_NAME = 'contacts';
|
||||
|
||||
var init = function init() {
|
||||
info = document.getElementById('info');
|
||||
fillButton = document.getElementById('fillDS');
|
||||
resetButton = document.getElementById('resetDS');
|
||||
|
||||
fillButton.addEventListener('click', handleEvent);
|
||||
resetButton.addEventListener('click', handleEvent);
|
||||
|
||||
initDS();
|
||||
};
|
||||
|
||||
function handleEvent(evt) {
|
||||
var btn = evt.target.id;
|
||||
|
||||
switch (btn) {
|
||||
case 'fillDS':
|
||||
fillButton.disabled = true;
|
||||
LinkedIn.initLogin(store, function() {
|
||||
LinkedIn.importContacts(function() {
|
||||
store.getLength().then(function(count) {
|
||||
info.textContent = count + ' elements';
|
||||
});
|
||||
fillButton.disabled = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'resetDS':
|
||||
store.clear().then(function() {
|
||||
store.getLength().then(function(count) {
|
||||
info.textContent = count + ' elements';
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function initDS() {
|
||||
function storeError() {
|
||||
info.textContent = 'Error getting store';
|
||||
}
|
||||
|
||||
if (!navigator.getDataStores) {
|
||||
info.textContent = 'NO DataStore API!';
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.getDataStores(DS_NAME).then(function(ds) {
|
||||
if (!ds || ds.length < 1) {
|
||||
storeError();
|
||||
return;
|
||||
}
|
||||
ds.forEach(function onDs(datastore) {
|
||||
if (datastore.owner.indexOf('provider2')) {
|
||||
store = datastore;
|
||||
console.log('Got store ' + store.owner);
|
||||
}
|
||||
});
|
||||
|
||||
store.getLength().then(function(count) {
|
||||
info.textContent = count + ' elements';
|
||||
});
|
||||
}, function() {
|
||||
storeError();
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
App.init();
|
||||
177
gaia/dev_apps/contacts-ds-provider2/js/linkedin.js
Executable file
177
gaia/dev_apps/contacts-ds-provider2/js/linkedin.js
Executable file
|
|
@ -0,0 +1,177 @@
|
|||
'use strict';
|
||||
|
||||
var accessURI = 'https://www.linkedin.com/uas/oauth2/authorization?response_type=code' +
|
||||
'&client_id=773tsorjqd8pqw' +
|
||||
'&scope=r_fullprofile%20r_emailaddress%20r_network' +
|
||||
'&state=' + (new Date()) +
|
||||
'&redirect_uri=http://127.0.0.1/li';
|
||||
|
||||
var LinkedIn = function LinkedIn() {
|
||||
|
||||
var accessToken = null;
|
||||
var datastore = null;
|
||||
|
||||
var initLogin = function(ds, cb) {
|
||||
datastore = ds;
|
||||
accessToken = localStorage.accessToken;
|
||||
|
||||
if (accessToken) {
|
||||
cb(accessToken);
|
||||
return;
|
||||
}
|
||||
|
||||
var authWindow = window.open(accessURI);
|
||||
window.addEventListener('message', function(evt) {
|
||||
authWindow.close();
|
||||
var code = evt.data.code;
|
||||
|
||||
exchangeAuthCode(code, cb);
|
||||
});
|
||||
};
|
||||
|
||||
var getContacts = function getContacts(cb) {
|
||||
getLinkedinPeople(cb);
|
||||
};
|
||||
|
||||
var importContacts = function importContacts(cb) {
|
||||
getContacts(function(contacts) {
|
||||
// Save contacts to local ds
|
||||
doImportContacts(contacts, cb);
|
||||
});
|
||||
};
|
||||
|
||||
function doImportContacts(contacts, cb) {
|
||||
if (!contacts || contacts.length === 0) {
|
||||
if (typeof cb === 'function') {
|
||||
cb();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var contact = prepareForDS(contacts[0]);
|
||||
|
||||
function continuee() {
|
||||
var rest = contacts.slice(1);
|
||||
if (rest && rest.length > -1) {
|
||||
doImportContacts(rest, cb);
|
||||
}
|
||||
}
|
||||
|
||||
datastore.add(contact).then(function(id) {
|
||||
console.add('Added contact with id ' + id);
|
||||
continuee();
|
||||
|
||||
}, function() {
|
||||
console.add('Error saving contact ');
|
||||
continuee();
|
||||
});
|
||||
}
|
||||
|
||||
function prepareForDS(contact) {
|
||||
// Initialy dont do any extra processing
|
||||
return contact;
|
||||
}
|
||||
|
||||
function getLinkedinPeople(cb) {
|
||||
var url = 'https://api.linkedin.com/v1/people/~/connections?oauth2_access_token=' + accessToken;
|
||||
|
||||
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
|
||||
xhr.open('GET', url, true);
|
||||
xhr.addEventListener('load', function dataLoaded(e) {
|
||||
if (xhr.status === 200 || xhr.status === 0) {
|
||||
parseContacts(xhr.responseXML, cb);
|
||||
}
|
||||
});
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function parseContacts(xml, cb) {
|
||||
var contactsElements = xml.querySelectorAll('person');
|
||||
contactsElements = Array.prototype.slice.call(contactsElements);
|
||||
parseIterative(contactsElements, [], cb);
|
||||
}
|
||||
|
||||
function parseIterative(unparsedList, parsedList, cb) {
|
||||
if (!unparsedList || unparsedList.length === 0) {
|
||||
cb(parsedList);
|
||||
return;
|
||||
}
|
||||
|
||||
var unparsed = unparsedList[0];
|
||||
var rest = unparsedList.slice(1);
|
||||
|
||||
parseContact(unparsed, function(contact) {
|
||||
parsedList.push(contact);
|
||||
parseIterative(rest, parsedList, cb);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function parseContact(raw, cb) {
|
||||
var contact = {};
|
||||
|
||||
contact.uid = raw.querySelector('id').textContent;
|
||||
contact.givenName = [];
|
||||
contact.givenName[0] = raw.querySelector('first-name') ?
|
||||
raw.querySelector('first-name').textContent || '' : '';
|
||||
contact.familyName = [];
|
||||
contact.familyName[0] = raw.querySelector('last-name') ?
|
||||
raw.querySelector('last-name').textContent || '' : '';
|
||||
contact.name = [contact.givenName[0] + ' ' + contact.familyName[0]];
|
||||
contact.org = [];
|
||||
contact.org[0] = raw.querySelector('headline') ?
|
||||
raw.querySelector('headline').textContent || '' : '';
|
||||
|
||||
// Parse photo here
|
||||
var photoUrl = raw.querySelector('picture-url');
|
||||
if (photoUrl) {
|
||||
photoUrl = photoUrl.textContent;
|
||||
var xhr = new XMLHttpRequest({mozSystem: true});
|
||||
xhr.open('GET', photoUrl, true);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.addEventListener('load', function onImageLoaded(e) {
|
||||
if (xhr.status === 0 || xhr.status === 200) {
|
||||
contact.photo = [xhr.response];
|
||||
}
|
||||
cb(contact);
|
||||
});
|
||||
xhr.send();
|
||||
} else {
|
||||
cb(contact);
|
||||
}
|
||||
}
|
||||
|
||||
function exchangeAuthCode(code, cb) {
|
||||
var url = 'https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code' +
|
||||
'&code=' + code +
|
||||
'&redirect_uri=http://127.0.0.1/li' +
|
||||
'&client_id=773tsorjqd8pqw' +
|
||||
'&client_secret=oX6W3js86FIfNtZH';
|
||||
|
||||
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
|
||||
xhr.open('POST', url, true);
|
||||
xhr.addEventListener('load', function dataLoaded(e) {
|
||||
if (xhr.status === 200 || xhr.status === 0) {
|
||||
var response = xhr.response;
|
||||
if (typeof response === 'string') {
|
||||
response = JSON.parse(response);
|
||||
}
|
||||
|
||||
accessToken = response.access_token;
|
||||
localStorage.accessToken = accessToken;
|
||||
cb(accessToken);
|
||||
} else {
|
||||
console.error('Could not get an access token from url ' + url);
|
||||
}
|
||||
});
|
||||
xhr.send();
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
initLogin: initLogin,
|
||||
getContacts: getContacts,
|
||||
importContacts: importContacts
|
||||
};
|
||||
|
||||
}();
|
||||
36
gaia/dev_apps/contacts-ds-provider2/js/redirect.js
Executable file
36
gaia/dev_apps/contacts-ds-provider2/js/redirect.js
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
'use strict';
|
||||
|
||||
var Redirect = function Redirect() {
|
||||
|
||||
var ORIGIN = document.location.protocol + '//' +
|
||||
document.location.host;
|
||||
|
||||
var init = function init() {
|
||||
var parameters = {};
|
||||
|
||||
var dataStart = document.location.href.indexOf('?');
|
||||
var params = document.location.href.substring(dataStart + 1);
|
||||
|
||||
if (dataStart !== -1) {
|
||||
var elements = params.split('&');
|
||||
|
||||
elements.forEach(function(p) {
|
||||
var values = p.split('=');
|
||||
parameters[values[0]] = values[1];
|
||||
});
|
||||
console.log('-----> Post message:');
|
||||
console.log(JSON.stringify(parameters));
|
||||
|
||||
window.opener.postMessage(parameters, ORIGIN);
|
||||
window.close();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
'init': init
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
Redirect.init();
|
||||
27
gaia/dev_apps/contacts-ds-provider2/manifest.webapp
Executable file
27
gaia/dev_apps/contacts-ds-provider2/manifest.webapp
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "LI Contacts DS",
|
||||
"type": "certified",
|
||||
"launch_path": "/index.html",
|
||||
"datastores-owned": {
|
||||
"contacts": {
|
||||
"access": "readwrite",
|
||||
"description": "Provider 2 contacts"
|
||||
}
|
||||
},
|
||||
"redirects": [
|
||||
{"from": "http://127.0.0.1/li",
|
||||
"to": "/redirect.html"}
|
||||
],
|
||||
"permissions": {
|
||||
"systemXHR": {
|
||||
"description": "This permission is require to contact Linked In serves"
|
||||
}
|
||||
},
|
||||
"icons": {
|
||||
"84": "/style/icons/default_84.png",
|
||||
"126": "/style/icons/default_126.png",
|
||||
"142": "/style/icons/default_142.png",
|
||||
"189": "/style/icons/default_189.png",
|
||||
"284": "/style/icons/default_284.png"
|
||||
}
|
||||
}
|
||||
11
gaia/dev_apps/contacts-ds-provider2/redirect.html
Executable file
11
gaia/dev_apps/contacts-ds-provider2/redirect.html
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>OAuth Redirection</title>
|
||||
<script defer src="js/redirect.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_126.png
Executable file
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_126.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_142.png
Executable file
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_142.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_189.png
Executable file
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_189.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_284.png
Executable file
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_284.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_84.png
Executable file
BIN
gaia/dev_apps/contacts-ds-provider2/style/icons/default_84.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Loading…
Reference in a new issue