Merge pull request #80 from whiteout-io/dev/android

Add CCA scripts and css optimizations for Android
This commit is contained in:
Tankred Hase 2014-06-26 15:17:22 +02:00
commit 2500b46f3a
10 changed files with 151 additions and 45 deletions

11
res/build_cca.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
# go to root
cd `dirname $0`
cd ..
DIR=release/cca
rm -rf $DIR
mkdir -p $DIR
cca create $DIR/Whiteout --link-to=dist/manifest.json

9
res/run_cca.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
# go to root
cd `dirname $0`
cd ..
cd release/cca/Whiteout
#cca run ios
cca run android

View File

@ -19,24 +19,32 @@ define(function() {
return; return;
} }
// get a fresh oauth token // try reading email address from local storage
self._oauth.getOAuthToken(function(err, token) { self.getEmailAddressFromConfig(function(err, emailAddress) {
if (err) { if (err) {
callback(err); callback(err);
return; return;
} }
// get email address for the token // get a fresh oauth token
self.queryEmailAddress(token, function(err, emailAddress) { self._oauth.getOAuthToken(emailAddress, function(err, token) {
if (err) { if (err) {
callback(err); callback(err);
return; return;
} }
callback(null, { // get email address for the token
emailAddress: emailAddress, self.queryEmailAddress(token, function(err, emailAddress) {
oauthToken: token, if (err) {
sslCert: certificate callback(err);
return;
}
callback(null, {
emailAddress: emailAddress,
oauthToken: token,
sslCert: certificate
});
}); });
}); });
}); });

File diff suppressed because one or more lines are too long

View File

@ -12,19 +12,34 @@ define(function() {
/** /**
* Request an OAuth token from chrome for gmail users * Request an OAuth token from chrome for gmail users
*/ */
OAuth.prototype.getOAuthToken = function(callback) { OAuth.prototype.getOAuthToken = function(emailAddress, callback) {
// get OAuth Token from chrome var idOptions = {
chrome.identity.getAuthToken({ interactive: true
'interactive': true };
}, function(token) {
if ((chrome && chrome.runtime && chrome.runtime.lastError) || !token) { // check which runtime the app is running under
callback({ chrome.runtime.getPlatformInfo(function(platformInfo) {
errMsg: 'Error fetching an OAuth token for the user!' if ((chrome && chrome.runtime && chrome.runtime.lastError) || !platformInfo) {
}); callback(new Error('Error getting chrome platform info!'));
return; return;
} }
callback(null, token); if (emailAddress && platformInfo.os.indexOf('android') !== -1) {
// set accountHint so that native Android account picker does not show up each time
idOptions.accountHint = emailAddress;
}
// get OAuth Token from chrome
chrome.identity.getAuthToken(idOptions, function(token) {
if ((chrome && chrome.runtime && chrome.runtime.lastError) || !token) {
callback({
errMsg: 'Error fetching an OAuth token for the user!'
});
return;
}
callback(null, token);
});
}); });
}; };
@ -38,7 +53,7 @@ define(function() {
// fetch gmail user's email address from the Google Authorization Server // fetch gmail user's email address from the Google Authorization Server
this._googleApi.get({ this._googleApi.get({
uri: '/oauth2/v1/tokeninfo?access_token=' + token uri: '/oauth2/v3/userinfo?access_token=' + token
}, function(err, info) { }, function(err, info) {
if (err || !info || !info.email) { if (err || !info || !info.email) {
callback({ callback({

View File

@ -13,6 +13,7 @@
}, },
"notifications", "notifications",
"https://keys-test.whiteout.io/", "https://keys-test.whiteout.io/",
"https://www.googleapis.com/",
"identity", { "identity", {
"socket": [ "socket": [
"tcp-connect:imap.gmail.com:993", "tcp-connect:imap.gmail.com:993",
@ -24,7 +25,7 @@
"oauth2": { "oauth2": {
"client_id": "440907777130.apps.googleusercontent.com", "client_id": "440907777130.apps.googleusercontent.com",
"scopes": [ "scopes": [
"https://www.googleapis.com/auth/userinfo.email", "email",
"https://mail.google.com/" "https://mail.google.com/"
] ]
}, },

12
src/manifest.mobile.json Normal file
View File

@ -0,0 +1,12 @@
{
"packageId": "io.whiteout.WhiteoutMail",
"versionCode": 1,
"CFBundleVersion": "1.1.1",
// platform overrides
"ios": {
"oauth2": {
"client_id": "440907777130-m0cn01eot554ik1h70hfcmvidnq61oer.apps.googleusercontent.com"
}
}
}

View File

@ -1,29 +1,25 @@
.main-content { .main-content {
@include clearfix(); @include clearfix();
height: 100%; height: 100%;
overflow: hidden;
backface-visibility: hidden;
// double in modile to allow slide transition
@include respond-to(mobile) {
width: 200%; // this currently causes a smear effect bug on mail-list header in safari
transition: transform $time-nav-animation ease-in-out;
}
} }
.column { .column {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
// half of main-content in mobile mode to allow slide transition
@include respond-to(mobile) { @include respond-to(mobile) {
width: 50%; display: none;
width: 100%;
} }
} }
.column-left { .column-left {
float: left; float: left;
@include respond-to(mobile) {
display: block;
}
@include respond-to(desktop) { @include respond-to(desktop) {
width: $content-nav-width; width: $content-nav-width;
border-right: 1px solid $color-grey-light; border-right: 1px solid $color-grey-light;
@ -32,6 +28,11 @@
.shift-right { .shift-right {
@include respond-to(mobile) { @include respond-to(mobile) {
transform: translateX(-50%); .column {
display: block;
}
.column-left {
display: none;
}
} }
} }

View File

@ -20,17 +20,19 @@ define(function(require) {
afterEach(function() {}); afterEach(function() {});
describe('getCredentials', function() { describe('getCredentials', function() {
var getCertificateStub, queryEmailAddressStub; var getCertificateStub, queryEmailAddressStub, getEmailAddressFromConfigStub;
beforeEach(function() { beforeEach(function() {
getCertificateStub = sinon.stub(auth, 'getCertificate'); getCertificateStub = sinon.stub(auth, 'getCertificate');
queryEmailAddressStub = sinon.stub(auth, 'queryEmailAddress'); queryEmailAddressStub = sinon.stub(auth, 'queryEmailAddress');
getEmailAddressFromConfigStub = sinon.stub(auth, 'getEmailAddressFromConfig');
}); });
it('should work', function(done) { it('should work', function(done) {
getCertificateStub.yields(null, 'cert'); getCertificateStub.yields(null, 'cert');
getEmailAddressFromConfigStub.yields(null, 'asdf@example.com');
queryEmailAddressStub.withArgs('token').yields(null, 'asdf@example.com'); queryEmailAddressStub.withArgs('token').yields(null, 'asdf@example.com');
oauthStub.getOAuthToken.yields(null, 'token'); oauthStub.getOAuthToken.withArgs('asdf@example.com').yields(null, 'token');
auth.getCredentials({}, function(err, credentials) { auth.getCredentials({}, function(err, credentials) {
expect(err).to.not.exist; expect(err).to.not.exist;
@ -53,6 +55,7 @@ define(function(require) {
it('should fail due to error in getOAuthToken', function(done) { it('should fail due to error in getOAuthToken', function(done) {
getCertificateStub.yields(null, 'cert'); getCertificateStub.yields(null, 'cert');
getEmailAddressFromConfigStub.yields(null, 'asdf@example.com');
oauthStub.getOAuthToken.yields(new Error()); oauthStub.getOAuthToken.yields(new Error());
auth.getCredentials({}, function(err, credentials) { auth.getCredentials({}, function(err, credentials) {
@ -64,6 +67,7 @@ define(function(require) {
it('should fail due to error in queryEmailAddress', function(done) { it('should fail due to error in queryEmailAddress', function(done) {
getCertificateStub.yields(null, 'cert'); getCertificateStub.yields(null, 'cert');
getEmailAddressFromConfigStub.yields(null, 'asdf@example.com');
queryEmailAddressStub.withArgs('token').yields(new Error()); queryEmailAddressStub.withArgs('token').yields(new Error());
oauthStub.getOAuthToken.yields(null, 'token'); oauthStub.getOAuthToken.yields(null, 'token');

View File

@ -6,22 +6,31 @@ define(function(require) {
expect = chai.expect; expect = chai.expect;
describe('OAuth unit tests', function() { describe('OAuth unit tests', function() {
var oauth, googleApiStub, identityStub; var oauth, googleApiStub, identityStub, getPlatformInfoStub,
testEmail = 'test@example.com';
beforeEach(function() { beforeEach(function() {
googleApiStub = sinon.createStubInstance(RestDAO); googleApiStub = sinon.createStubInstance(RestDAO);
oauth = new OAuth(googleApiStub); oauth = new OAuth(googleApiStub);
window.chrome = window.chrome || {}; window.chrome = window.chrome || {};
window.chrome.identity = window.chrome.identity || {}; window.chrome.identity = window.chrome.identity || {};
if (typeof window.chrome.identity.getAuthToken !== 'function') { if (typeof window.chrome.identity.getAuthToken !== 'function') {
window.chrome.identity.getAuthToken = function() {}; window.chrome.identity.getAuthToken = function() {};
} }
identityStub = sinon.stub(window.chrome.identity, 'getAuthToken'); identityStub = sinon.stub(window.chrome.identity, 'getAuthToken');
window.chrome.runtime = window.chrome.runtime || {};
if (typeof window.chrome.runtime.getPlatformInfo !== 'function') {
window.chrome.runtime.getPlatformInfo = function() {};
}
getPlatformInfoStub = sinon.stub(window.chrome.runtime, 'getPlatformInfo');
}); });
afterEach(function() { afterEach(function() {
identityStub.restore(); identityStub.restore();
getPlatformInfoStub.restore();
}); });
describe('isSupported', function() { describe('isSupported', function() {
@ -31,10 +40,46 @@ define(function(require) {
}); });
describe('getOAuthToken', function() { describe('getOAuthToken', function() {
it('should work', function(done) { it('should work for empty emailAddress', function(done) {
identityStub.yields('token'); getPlatformInfoStub.yields({
os: 'android'
});
identityStub.withArgs({
interactive: true
}).yields('token');
oauth.getOAuthToken(function(err, token) { oauth.getOAuthToken(undefined, function(err, token) {
expect(err).to.not.exist;
expect(token).to.equal('token');
done();
});
});
it('should work on android app', function(done) {
getPlatformInfoStub.yields({
os: 'android'
});
identityStub.withArgs({
interactive: true,
accountHint: testEmail
}).yields('token');
oauth.getOAuthToken(testEmail, function(err, token) {
expect(err).to.not.exist;
expect(token).to.equal('token');
done();
});
});
it('should work on desktop chrome', function(done) {
getPlatformInfoStub.yields({
os: 'mac'
});
identityStub.withArgs({
interactive: true
}).yields('token');
oauth.getOAuthToken(testEmail, function(err, token) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(token).to.equal('token'); expect(token).to.equal('token');
done(); done();
@ -42,9 +87,12 @@ define(function(require) {
}); });
it('should fail', function(done) { it('should fail', function(done) {
getPlatformInfoStub.yields({
os: 'android'
});
identityStub.yields(); identityStub.yields();
oauth.getOAuthToken(function(err, token) { oauth.getOAuthToken(testEmail, function(err, token) {
expect(err).to.exist; expect(err).to.exist;
expect(token).to.not.exist; expect(token).to.not.exist;
done(); done();
@ -55,7 +103,7 @@ define(function(require) {
describe('queryEmailAddress', function() { describe('queryEmailAddress', function() {
it('should work', function(done) { it('should work', function(done) {
googleApiStub.get.withArgs({ googleApiStub.get.withArgs({
uri: '/oauth2/v1/tokeninfo?access_token=token' uri: '/oauth2/v3/userinfo?access_token=token'
}).yields(null, { }).yields(null, {
email: 'asdf@example.com' email: 'asdf@example.com'
}); });
@ -77,7 +125,7 @@ define(function(require) {
it('should fail due to error in rest api', function(done) { it('should fail due to error in rest api', function(done) {
googleApiStub.get.withArgs({ googleApiStub.get.withArgs({
uri: '/oauth2/v1/tokeninfo?access_token=token' uri: '/oauth2/v3/userinfo?access_token=token'
}).yields(new Error()); }).yields(new Error());
oauth.queryEmailAddress('token', function(err, emailAddress) { oauth.queryEmailAddress('token', function(err, emailAddress) {