diff --git a/src/factories/GApi.factory.js b/src/factories/GApi.factory.js index 78d9f25..765f46e 100644 --- a/src/factories/GApi.factory.js +++ b/src/factories/GApi.factory.js @@ -1,10 +1,13 @@ (function() { 'use strict'; - angular.module('angular-google-gapi').factory('GApi', ['$q', 'GClient', 'GData', '$window', - function($q, GClient, GData, $window){ + angular.module('angular-google-gapi', []); +})(); +(function() { + 'use strict'; + angular.module('angular-google-gapi').factory('GApi', ['$q', 'GClient', '$window', 'GAuth', + function($q, GClient, $window, GAuth){ var apisLoad = []; - var observerCallbacks = []; function registerObserverCallback(api, method, params, auth, deferred){ @@ -19,12 +22,15 @@ }; function load(api, version, url) { + + //logTimer("GApi.load: " + api); + var deferred = $q.defer(); GClient.get().then(function (){ $window.gapi.client.load(api, version, undefined, url).then(function(response) { var result = {'api': api, 'version': version, 'url': url}; if(response && response.hasOwnProperty('error')) { - console.log(version); + //logTimer(version); deferred.reject(result); } else { deferred.resolve(result); @@ -37,11 +43,12 @@ } function executeCallbacks(api){ + var apiName = api; for(var i= 0; i < observerCallbacks.length; i++){ var observerCallback = observerCallbacks[i]; - if ((observerCallback.api == apiName || observerCallback.apiLoad) && (observerCallback.auth == false || GData.isLogin() == true)) { + if ((observerCallback.api == apiName || observerCallback.apiLoad) && (observerCallback.auth == false || GAuth.isSignedIn() == true)) { runGapi(observerCallback.api, observerCallback.method, observerCallback.params, observerCallback.deferred); if (i > -1) { observerCallbacks.splice(i--, 1); @@ -51,10 +58,10 @@ observerCallbacks[i]['apiLoad'] = true; } }; - } - function createRequest(api, method, params) { + function createRequest(api, method, params) { + ////logTimer("GApi.createRequest: " + api); var pathMethod = method.split('.'); var api = $window.gapi.client[api]; for(var i= 0; i < pathMethod.length; i++) { @@ -83,6 +90,37 @@ return deferred.promise; } + //exponentialBackoff + function retryExecute(actionPromise, args) { + var queryResults = $q.defer(); + var iter = 0; + retry(actionPromise, iter); + function retry(actionPromise, iter) { + actionPromise.apply(this, args).then(function(body) { + queryResults.resolve(body); + }).catch(function(error){ + if((error.code == 403 && error.message.toLowerCase().indexOf('limit exceeded')>-1) || error.code == 503){ + var base = 2; + var ms = 1000; + var randomMilliseconds = Math.floor((Math.random() * 1000) + 1); + if(iter < 5){ + setTimeout(function(){ + retry(actionPromise, ++iter); + }, (ms * Math.pow(base, iter)) + randomMilliseconds); + } + else{ + queryResults.reject(error); + } + } + else{ + queryResults.reject(error); + } + }); + } + return queryResults.promise; + } + + return { executeCallbacks : function() { @@ -91,7 +129,6 @@ load: load, createRequest: createRequest, - execute: function(api, method, params){ if(arguments.length == 3) return execute(api, method, params, false); @@ -101,9 +138,9 @@ executeAuth: function(api, method, params){ if(arguments.length == 3) - return execute(api, method, params, true); + return retryExecute(execute, arguments); //return execute(api, method, params, true) if(arguments.length == 2) - return execute(api, method, null, true); + return retryExecute(execute, arguments); //return execute(api, method, null, true) }, } }]); diff --git a/src/factories/GAuth.factory.js b/src/factories/GAuth.factory.js index 32056ee..ca9c4d7 100644 --- a/src/factories/GAuth.factory.js +++ b/src/factories/GAuth.factory.js @@ -1,24 +1,32 @@ (function() { 'use strict'; - angular.module('angular-google-gapi').factory('GAuth', ['$rootScope', '$q', 'GClient', 'GApi', 'GData', '$interval', '$window', '$location', - function($rootScope, $q, GClient, GApi, GData, $interval, $window, $location){ - var isLoad = false; + angular.module('angular-google-gapi').factory('GAuth', ['$q', 'GClient', '$window', '$localstorage', + function($q, GClient, $window, $localstorage){ + var isLoad = false; var CLIENT_ID; var DOMAIN = undefined; - var SCOPE = 'https://www.googleapis.com/auth/userinfo.email'; + var SCOPE = ''; var RESPONSE_TYPE = 'token id_token'; + var gapiauth2GoogleAuth = null; function load(){ + //logt("GAuth.load function"); var deferred = $q.defer(); if (isLoad == false) { GClient.get().then(function (){ - $window.gapi.client.load('oauth2', 'v2', function() { + logt("GClient.get().then"); + $window.gapi.load('auth2', function() { + logt("auth2 loaded"); isLoad = true; - deferred.resolve(); + deferred.resolve(); }); + }).catch(function (resp){ + //logTimer(resp); + deferred.reject(); }); - } else { + } + else { deferred.resolve(); } return deferred.promise; @@ -26,19 +34,60 @@ function signin(mode, authorizeCallback) { - load().then(function (){ - var config = {client_id: CLIENT_ID, scope: SCOPE, immediate: false, authuser: -1, response_type: RESPONSE_TYPE}; - if(mode) { - config.user_id = GData.getUserId(); - config.immediate = true; + //logTimer("GAuth.signin: " + mode); + + function executeSignin(mode, authorizeCallback){ + + //logTimer("GAuth.executeSignin: " + mode); + + if (gapiauth2GoogleAuth){ + if (gapiauth2GoogleAuth.isSignedIn.get() == true) { + //logTimer("GAuth.executeSignin RESOLVED! ARRIBA"); + //resp.signIn().then(authorizeCallback); + authorizeCallback(); + } + else{ + //logTimer("GAuth.executeSignin RESOLVED! ABAJO"); + gapiauth2GoogleAuth.signIn({prompt: 'select_account'}).then(authorizeCallback); + } + } + else{ + + $window.gapi.auth2.init({ + client_id: CLIENT_ID, + fetch_basic_profile: false, + scope: SCOPE, + authuser: -1, + immediate: false + }).then(function (resp) { + + gapiauth2GoogleAuth = resp; + + if (gapiauth2GoogleAuth.isSignedIn.get() == true) { + //logTimer("GAuth.executeSignin RESOLVED! ARRIBA"); + //resp.signIn().then(authorizeCallback); + authorizeCallback(); + } + else{ + //logTimer("GAuth.executeSignin RESOLVED! ABAJO"); + gapiauth2GoogleAuth.signIn({prompt: 'select_account'}).then(authorizeCallback); + } + }); } - if(DOMAIN != undefined) - config.hd = DOMAIN; - $window.gapi.auth.authorize(config, authorizeCallback); - }); + } + + if(!mode && isLoad === true){ + // don't break the caller stack with async tasks + executeSignin(mode, authorizeCallback); + } else { + load().then(function (){ + executeSignin(mode, authorizeCallback); + }); + } } function offline() { + /* var deferred = $q.defer(); var origin = $location.protocol() + "//" + $location.hostname(); if($location.port() != "" || ($location.port() != 443 && $location.protocol()== "https")) { @@ -73,24 +122,7 @@ } return deferred.promise; - } - - function getUser() { - - var deferred = $q.defer(); - $window.gapi.client.oauth2.userinfo.get().execute(function(resp) { - if (!resp.code) { - GData.isLogin(true); - GApi.executeCallbacks(); - if (!resp.name || 0 === resp.name.length) - resp.name = resp.email; - GData.getUser(resp); - deferred.resolve(resp); - } else { - deferred.reject(); - } - }); - return deferred.promise; + */ } return { @@ -106,64 +138,76 @@ setScope: function(scope) { SCOPE = scope; }, + + load: load, checkAuth: function(){ + + logt("GAuth.checkAuth"); var deferred = $q.defer(); - signin(true, function() { - getUser().then(function (user) { - deferred.resolve(user); - }, function () { - deferred.reject(); - }); - }); + load().then(function (){ + $window.gapi.auth2.init({ + client_id: CLIENT_ID, + fetch_basic_profile: false, + scope: SCOPE, + authuser: -1, + immediate: false + }).then(function (resp) { + gapiauth2GoogleAuth = resp; + if (resp.isSignedIn.get() == true) { + deferred.resolve(); + } + else{ + deferred.reject(); + } + }); + }); + return deferred.promise; }, login: function(){ var deferred = $q.defer(); signin(false, function() { - getUser().then(function (user) { - deferred.resolve(); - }, function () { - deferred.reject(); - }); + deferred.resolve(); }); return deferred.promise; }, - setToken: function(token){ + getToken: function(){ var deferred = $q.defer(); load().then(function (){ - $window.gapi.auth.setToken(token); - getUser().then(function () { - deferred.resolve(); - }, function () { - deferred.reject(); + deferred.resolve(gapiauth2GoogleAuth.currentUser.get().getAuthResponse().access_token); }); - }); return deferred.promise; }, - getToken: function(){ + logout: function(){ var deferred = $q.defer(); - load().then(function (){ - deferred.resolve($window.gapi.auth.getToken()); + load().then(function() { + gapiauth2GoogleAuth.signOut().then(function() { + deferred.resolve(); + }); }); return deferred.promise; }, - logout: function(){ + grant: function(scopes){ var deferred = $q.defer(); - load().then(function() { - $window.gapi.auth.setToken(null); - GData.isLogin(false); - GData.getUser(null); - deferred.resolve(); - }); + + gapiauth2GoogleAuth.currentUser.get().grant({'scope': scopes}).then( + function(success){ + deferred.resolve(); + }, + function(fail){ + deferred.reject(); + }); + return deferred.promise; - }, + }, offline: function(){ + /* var deferred = $q.defer(); offline().then( function(code){ deferred.resolve(code); @@ -171,10 +215,12 @@ deferred.reject(); }); return deferred.promise; + */ }, - + isSignedIn: function(){ + return gapiauth2GoogleAuth.isSignedIn.get(); + }, } - }]); })(); \ No newline at end of file diff --git a/src/factories/GClient.factory.js b/src/factories/GClient.factory.js index 4d00abc..f68b529 100644 --- a/src/factories/GClient.factory.js +++ b/src/factories/GClient.factory.js @@ -3,18 +3,31 @@ angular.module('angular-google-gapi').factory('GClient', ['$document', '$q', '$window', function ($document, $q, $window) { + //logTimer("GClient LOAD Factory"); + var LOAD_GAE_API = false; var LOADING_GAE_API = false; - var URL = 'https://apis.google.com/js/client.js?onload=_gapiOnLoad'; + var URL = 'https://apis.google.com/js/client:platform.js?onload=_gapiOnLoad'; var API_KEY = null; var OBSERVER_CALLBACKS = []; function loadScript(src) { + + //logTimer("GClient.loadScript: " + src); + var deferred = $q.defer(); $window._gapiOnLoad = function(){ deferred.resolve(); } var script = $document[0].createElement('script'); + + var a = $document[0].createAttribute("async"); + script.setAttributeNode(a); + + a = $document[0].createAttribute("defer"); + script.setAttributeNode(a); + + script.onerror = function (e) { $timeout(function () { deferred.reject(e); @@ -28,6 +41,9 @@ return { get: function(){ + + //logTimer("GClient.get - LOAD_GAE_API:" + LOAD_GAE_API); + var deferred = $q.defer(); if(LOAD_GAE_API) deferred.resolve(); @@ -36,11 +52,16 @@ OBSERVER_CALLBACKS.push(deferred); } else { LOADING_GAE_API = true; + + //logTimer("GClient.get - URL:" + URL); + + //logTimer("PREPARE loadScript" + URL); loadScript(URL).then(function() { $window.gapi.client.setApiKey(API_KEY) LOAD_GAE_API = true; LOADING_GAE_API = false; deferred.resolve(); + //logTimer("FINISHED loadScript" + URL); for(var i= 0; i < OBSERVER_CALLBACKS.length; i++){ OBSERVER_CALLBACKS[i].resolve(); } @@ -51,6 +72,8 @@ }, setApiKey: function(apiKey){ + //logTimer("GClient.setApiKey: " + apiKey); + API_KEY = apiKey; if(LOAD_GAE_API) { $window.gapi.client.setApiKey(API_KEY); diff --git a/src/factories/GData.factory.js b/src/factories/GData.factory.js deleted file mode 100644 index 01114b5..0000000 --- a/src/factories/GData.factory.js +++ /dev/null @@ -1,42 +0,0 @@ -(function() { - 'use strict'; - angular.module('angular-google-gapi').factory('GData', ['$rootScope', - function ($rootScope) { - - $rootScope.gapi = {}; - - var isLogin = false; - var user = null; - var userId = null; - - return { - - getUserId : function() { - return userId; - }, - - setUserId : function(id) { - userId = id; - }, - - isLogin : function(value) { - if(arguments.length == 0) - return isLogin; - isLogin = value; - $rootScope.gapi.login = value; - }, - - getUser : function(value) { - if(arguments.length == 0) - return user; - user = value; - if(value !== null) { - userId = value.id; - } - - } - - } - - }]); -})(); \ No newline at end of file