| Index: lib/src/google-signin/google-signin-aware.html
 | 
| diff --git a/lib/src/google-signin/google-signin-aware.html b/lib/src/google-signin/google-signin-aware.html
 | 
| index ab8e045288482fe6e58762aa02734feacc5a8911..e28d8be4519eb3bbfebc6fa6c3b2ae9f1da4a0b2 100644
 | 
| --- a/lib/src/google-signin/google-signin-aware.html
 | 
| +++ b/lib/src/google-signin/google-signin-aware.html
 | 
| @@ -13,7 +13,8 @@
 | 
|        'appPackageName': 'apppackagename',
 | 
|        'clientId': 'clientid',
 | 
|        'cookiePolicy': 'cookiepolicy',
 | 
| -      'requestVisibleActions': 'requestvisibleactions'
 | 
| +      'requestVisibleActions': 'requestvisibleactions',
 | 
| +      'hostedDomain': 'hostedDomain'
 | 
|      };
 | 
|  
 | 
|      /**
 | 
| @@ -97,6 +98,50 @@
 | 
|            this._requestVisibleActions = val;
 | 
|        },
 | 
|  
 | 
| +     /**
 | 
| +       * oauth2 argument, set by google-signin-aware
 | 
| +       */
 | 
| +      _hostedDomain: '',
 | 
| +
 | 
| +      get hostedDomain() {
 | 
| +        return this._hostedDomain;
 | 
| +      },
 | 
| +
 | 
| +      set hostedDomain(val) {
 | 
| +        if (this._hostedDomain && val && val != this._hostedDomain) {
 | 
| +          throw new Error('hostedDomain cannot change. Values do not match. New: ' + val + ' Old: ' + this._hostedDomain);
 | 
| +        }
 | 
| +        if (val)
 | 
| +          this._hostedDomain = val;
 | 
| +      },
 | 
| +
 | 
| +      /** Is offline access currently enabled in the google-signin-aware element? */
 | 
| +      _offline: false,
 | 
| +
 | 
| +      get offline() {
 | 
| +        return this._offline;
 | 
| +      },
 | 
| +
 | 
| +      set offline(val) {
 | 
| +        this._offline = val;
 | 
| +        this.updateAdditionalAuth();
 | 
| +      },
 | 
| +
 | 
| +      /** Should we force a re-prompt for offline access? */
 | 
| +      _offlineAlwaysPrompt: false,
 | 
| +
 | 
| +      get offlineAlwaysPrompt() {
 | 
| +        return this._offlineAlwaysPrompt;
 | 
| +      },
 | 
| +
 | 
| +      set offlineAlwaysPrompt(val) {
 | 
| +        this._offlineAlwaysPrompt = val;
 | 
| +        this.updateAdditionalAuth();
 | 
| +      },
 | 
| +
 | 
| +      /** Have we already gotten offline access from Google during this session? */
 | 
| +      offlineGranted: false,
 | 
| +
 | 
|        /** <google-js-api> */
 | 
|        _apiLoader: null,
 | 
|  
 | 
| @@ -142,7 +187,8 @@
 | 
|          var auth = gapi.auth2.init({
 | 
|            'client_id': this.clientId,
 | 
|            'cookie_policy': this.cookiePolicy,
 | 
| -          'scope': this.requestedScopes
 | 
| +          'scope': this.requestedScopes,
 | 
| +          'hosted_domain': this.hostedDomain
 | 
|          });
 | 
|  
 | 
|          auth.currentUser.listen(this.handleUserUpdate.bind(this));
 | 
| @@ -179,6 +225,12 @@
 | 
|          }
 | 
|        },
 | 
|  
 | 
| +      setOfflineCode: function(code) {
 | 
| +        for (var i=0; i<this.signinAwares.length; i++) {
 | 
| +          this.signinAwares[i]._updateOfflineCode(code);
 | 
| +        }
 | 
| +      },
 | 
| +
 | 
|        /** convert scope string to scope array */
 | 
|        strToScopeArray: function(str) {
 | 
|          if (!str) {
 | 
| @@ -237,10 +289,14 @@
 | 
|        /** update status of _needAdditionalAuth */
 | 
|        updateAdditionalAuth: function() {
 | 
|          var needMoreAuth = false;
 | 
| -        for (var i=0; i<this._requestedScopeArray.length; i++) {
 | 
| -          if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) === -1) {
 | 
| -            needMoreAuth = true;
 | 
| -            break;
 | 
| +        if ((this.offlineAlwaysPrompt || this.offline ) && !this.offlineGranted) {
 | 
| +          needMoreAuth = true;
 | 
| +        } else {
 | 
| +          for (var i=0; i<this._requestedScopeArray.length; i++) {
 | 
| +            if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) === -1) {
 | 
| +              needMoreAuth = true;
 | 
| +              break;
 | 
| +            }
 | 
|            }
 | 
|          }
 | 
|          if (this._needAdditionalAuth != needMoreAuth) {
 | 
| @@ -327,15 +383,40 @@
 | 
|  
 | 
|          var promise;
 | 
|          var user = gapi.auth2.getAuthInstance().currentUser.get();
 | 
| -        if (user.getGrantedScopes()) {
 | 
| -          // additional auth, skip multiple account dialog
 | 
| -          promise = user.grant(params);
 | 
| +        if (!(this.offline || this.offlineAlwaysPrompt)) {
 | 
| +          if (user.getGrantedScopes()) {
 | 
| +            // additional auth, skip multiple account dialog
 | 
| +            promise = user.grant(params);
 | 
| +          } else {
 | 
| +            // initial signin
 | 
| +            promise = gapi.auth2.getAuthInstance().signIn(params);
 | 
| +          }
 | 
|          } else {
 | 
| -          // initial signin
 | 
| -          promise = gapi.auth2.getAuthInstance().signIn(params);
 | 
| +          params.redirect_uri = 'postmessage';
 | 
| +          if (this.offlineAlwaysPrompt) {
 | 
| +            params.approval_prompt = 'force';
 | 
| +          }
 | 
| +
 | 
| +          // Despite being documented at https://goo.gl/tiO0Bk
 | 
| +          // It doesn't seem like user.grantOfflineAccess() actually exists in
 | 
| +          // the current version of the Google Sign-In JS client we're using
 | 
| +          // through GoogleWebComponents. So in the offline case, we will not
 | 
| +          // distinguish between a first auth and an additional one.
 | 
| +          promise = gapi.auth2.getAuthInstance().grantOfflineAccess(params);
 | 
|          }
 | 
|          promise.then(
 | 
| -          function success(newUser) {
 | 
| +          function success(response) {
 | 
| +            // If login was offline, response contains one string "code"
 | 
| +            // Otherwise it contains the user object already
 | 
| +            var newUser;
 | 
| +            if (response.code) {
 | 
| +              AuthEngine.offlineGranted = true;
 | 
| +              newUser = gapi.auth2.getAuthInstance().currentUser.get();
 | 
| +              AuthEngine.setOfflineCode(response.code);
 | 
| +            } else {
 | 
| +              newUser = response;
 | 
| +            }
 | 
| +
 | 
|              var authResponse = newUser.getAuthResponse();
 | 
|              // Let the current user listener trigger the changes.
 | 
|            },
 | 
| @@ -375,13 +456,38 @@ The `scopes` attribute allows you to specify which scope permissions are require
 | 
|  (e.g do you want to allow interaction with the Google Drive API).
 | 
|  
 | 
|  The `google-signin-aware-success` event is triggered when a user successfully
 | 
| -authenticates. The `google-signin-aware-signed-out` event is triggered
 | 
| -when a user explicitely signs out via the google-signin element.
 | 
| +authenticates. If either `offline` or `offlineAlwaysPrompt` is set to true, successful
 | 
| +authentication will also trigger the `google-signin-offline-success`event.
 | 
| +The `google-signin-aware-signed-out` event is triggered when a user explicitly
 | 
| +signs out via the google-signin element.
 | 
|  
 | 
|  You can bind to `isAuthorized` property to monitor authorization state.
 | 
|  ##### Example
 | 
|  
 | 
|      <google-signin-aware scopes="https://www.googleapis.com/auth/drive"></google-signin-aware>
 | 
| +
 | 
| +
 | 
| +##### Example with offline
 | 
| +    <template id="awareness" is="dom-bind">
 | 
| +      <google-signin-aware
 | 
| +          scopes="https://www.googleapis.com/auth/drive"
 | 
| +          offline
 | 
| +          on-google-signin-aware-success="handleSignin"
 | 
| +          on-google-signin-offline-success="handleOffline"></google-signin-aware>
 | 
| +    <\/template>
 | 
| +    <script>
 | 
| +      var aware = document.querySelector('#awareness');
 | 
| +      aware.handleSignin = function(response) {
 | 
| +        var user = gapi.auth2.getAuthInstance().currentUser.get();
 | 
| +        console.log('User name: ' + user.getBasicProfile().getName());
 | 
| +      };
 | 
| +      aware.handleOffline = function(response) {
 | 
| +        console.log('Offline code received: ' + response.detail.code);
 | 
| +        // Here you would POST response.detail.code to your webserver, which can
 | 
| +        // exchange the authorization code for an access token. More info at:
 | 
| +        // https://developers.google.com/identity/protocols/OAuth2WebServer
 | 
| +      };
 | 
| +    <\/script>
 | 
|  */
 | 
|      Polymer({
 | 
|  
 | 
| @@ -393,6 +499,13 @@ You can bind to `isAuthorized` property to monitor authorization state.
 | 
|         * @event google-signin-aware-success
 | 
|         */
 | 
|        /**
 | 
| +       * Fired when an offline authorization is successful.
 | 
| +       * @param {Object} detail
 | 
| +       * @param {string} detail.code The one-time authorization code from Google.
 | 
| +       *     Your application can exchange this for an `access_token` and `refresh_token`
 | 
| +       * @event google-signin-offline-success
 | 
| +       */
 | 
| +      /**
 | 
|         * Fired when this scope is not authorized
 | 
|         * @event google-signin-aware-signed-out
 | 
|         */
 | 
| @@ -434,6 +547,39 @@ You can bind to `isAuthorized` property to monitor authorization state.
 | 
|            observer: '_requestVisibleActionsChanged'
 | 
|          },
 | 
|  
 | 
| +        /**
 | 
| +         * The Google Apps domain to which users must belong to sign in.
 | 
| +         * See the relevant [docs](https://developers.google.com/identity/sign-in/web/reference) for more information.
 | 
| +         */
 | 
| +        hostedDomain: {
 | 
| +          type: String,
 | 
| +          observer: '_hostedDomainChanged'
 | 
| +        },
 | 
| +
 | 
| +       /**
 | 
| +         * Allows for offline `access_token` retrieval during the signin process.
 | 
| +         * See also `offlineAlwaysPrompt`. You only need to set one of the two; if both
 | 
| +         * are set, the behavior of `offlineAlwaysPrompt` will override `offline`.
 | 
| +         */
 | 
| +        offline: {
 | 
| +          type: Boolean,
 | 
| +          value: false,
 | 
| +          observer: '_offlineChanged'
 | 
| +        },
 | 
| +
 | 
| +        /**
 | 
| +          * Works the same as `offline` with the addition that it will always
 | 
| +          * force a re-prompt to the user, guaranteeing that you will get a
 | 
| +          * refresh_token even if the user has already granted offline access to
 | 
| +          * this application. You only need to set one of `offline` or
 | 
| +          * `offlineAlwaysPrompt`, not both.
 | 
| +          */
 | 
| +        offlineAlwaysPrompt: {
 | 
| +          type: Boolean,
 | 
| +          value: false,
 | 
| +          observer: '_offlineAlwaysPromptChanged'
 | 
| +        },
 | 
| +
 | 
|         /**
 | 
|           * The scopes to provide access to (e.g https://www.googleapis.com/auth/drive)
 | 
|           * and should be space-delimited.
 | 
| @@ -517,6 +663,18 @@ You can bind to `isAuthorized` property to monitor authorization state.
 | 
|          AuthEngine.requestVisibleActions = newVal;
 | 
|        },
 | 
|  
 | 
| +      _hostedDomainChanged: function(newVal, oldVal) {
 | 
| +        AuthEngine.hostedDomain = newVal;
 | 
| +      },
 | 
| +
 | 
| +      _offlineChanged: function(newVal, oldVal) {
 | 
| +        AuthEngine.offline = newVal;
 | 
| +      },
 | 
| +
 | 
| +      _offlineAlwaysPromptChanged: function(newVal, oldVal) {
 | 
| +        AuthEngine.offlineAlwaysPrompt = newVal;
 | 
| +      },
 | 
| +
 | 
|        _scopesChanged: function(newVal, oldVal) {
 | 
|          AuthEngine.requestScopes(newVal);
 | 
|          this._updateScopeStatus();
 | 
| @@ -533,6 +691,12 @@ You can bind to `isAuthorized` property to monitor authorization state.
 | 
|              this.fire('google-signin-aware-signed-out', user);
 | 
|            }
 | 
|          }
 | 
| +      },
 | 
| +
 | 
| +      _updateOfflineCode: function(code) {
 | 
| +        if (code) {
 | 
| +          this.fire('google-signin-offline-success', {code: code});
 | 
| +        }
 | 
|        }
 | 
|      });
 | 
|    })();
 | 
| 
 |