nebulab-dropbox
Version:
Client library for the Dropbox API
161 lines (146 loc) • 6.86 kB
text/coffeescript
# OAuth driver code common to Chrome apps and extensions.
#
# @private
# Application code should use {Dropbox.AuthDriver.ChromeApp} or
# {Dropbox.AuthDriver.ChromeExtension}.
class Dropbox.AuthDriver.ChromeBase extends Dropbox.AuthDriver.BrowserBase
# Sets up an OAuth driver for Chrome.
#
# @param {Object} options (optional) one or more of the options below
# @option options {String} scope embedded in the chrome.storage.local key
# that holds the authentication data; useful for having multiple OAuth
# tokens in a single application
constructor: (options) ->
super options
@storageKey = "dropbox_js_#{@scope}_credentials"
# Saves token information when appropriate.
onAuthStepChange: (client, callback) ->
switch client.authStep
when Dropbox.Client.RESET
@loadCredentials (credentials) ->
client.setCredentials credentials if credentials
callback()
when Dropbox.Client.DONE
@storeCredentials client.credentials(), callback
when Dropbox.Client.SIGNED_OUT
@forgetCredentials callback
when Dropbox.Client.ERROR
@forgetCredentials callback
else
callback()
# URL of the redirect receiver page that messages the app / extension.
#
# @see Dropbox.AuthDriver#url
url: ->
@receiverUrl
# Stores a Dropbox.Client's credentials in chrome.storage.local.
#
# @private
# onAuthStepChange calls this method during the authentication flow.
#
# @param {Object} credentials the result of a Drobpox.Client#credentials call
# @param {function()} callback called when the storing operation is complete
# @return {Dropbox.AuthDriver.BrowserBase} this, for easy call chaining
storeCredentials: (credentials, callback) ->
items= {}
items[@storageKey] = credentials
chrome.storage.local.set items, callback
@
# Retrieves a token and secret from chrome.storage.local.
#
# @private
# onAuthStepChange calls this method during the authentication flow.
#
# @param {function(?Object)} callback supplied with the credentials object
# stored by a previous call to
# Dropbox.AuthDriver.BrowserBase#storeCredentials; null if no credentials
# were stored, or if the previously stored credentials were deleted
# @return {Dropbox.AuthDriver.BrowserBase} this, for easy call chaining
loadCredentials: (callback) ->
chrome.storage.local.get @storageKey, (items) =>
callback items[@storageKey] or null
@
# Deletes information previously stored by a call to storeCredentials.
#
# @private
# onAuthStepChange calls this method during the authentication flow.
#
# @param {function()} callback called after the credentials are deleted
# @return {Dropbox.AuthDriver.BrowserBase} this, for easy call chaining
forgetCredentials: (callback) ->
chrome.storage.local.remove @storageKey, callback
@
# OAuth driver code specific to Chrome packaged applications.
#
# @see http://developer.chrome.com/apps/about_apps.html
class Dropbox.AuthDriver.ChromeApp extends Dropbox.AuthDriver.ChromeBase
# Sets up an OAuth driver for a Chrome packaged application.
#
# @param {Object} options (optional) one or more of the options below
# @option options {String} scope embedded in the chrome.storage.local key
# that holds the authentication data; useful for having multiple OAuth
# tokens in a single application
constructor: (options) ->
super options
@receiverUrl = "https://#{chrome.runtime.id}.chromiumapp.org/"
# Uses the Chrome identity API to drive the OAuth 2 flow.
#
# @see Dropbox.AuthDriver#doAuthorize
# @see http://developer.chrome.com/apps/identity.html
doAuthorize: (authUrl, stateParam, client, callback) ->
chrome.identity.launchWebAuthFlow url: authUrl, interactive: true,
(redirectUrl) =>
if @locationStateParam(redirectUrl) is stateParam
stateParam = false # Avoid having this matched in the future.
callback Dropbox.Util.Oauth.queryParamsFromUrl(redirectUrl)
# OAuth driver code specific to Chrome extensions.
class Dropbox.AuthDriver.ChromeExtension extends Dropbox.AuthDriver.ChromeBase
# Sets up an OAuth driver for a Chrome extension.
#
# @param {Object} options (optional) one or more of the options below
# @option options {String} scope embedded in the chrome.storage.local key
# that holds the authentication data; useful for having multiple OAuth
# tokens in a single application
# @option options {String} receiverPath the path of page that receives the
# /authorize redirect and calls {Dropbox.AuthDriver.Chrome.oauthReceiver};
# the path should be relative to the extension folder; by default, is
# 'chrome_oauth_receiver.html'
constructor: (options) ->
super options
receiverPath = (options and options.receiverPath) or
'chrome_oauth_receiver.html'
@receiverUrl = chrome.runtime.getURL receiverPath
# Shows the authorization URL in a new tab, waits for it to send a message.
#
# @see Dropbox.AuthDriver#doAuthorize
doAuthorize: (authUrl, stateParam, client, callback) ->
oauthTab = null
listener = (message, sender) =>
# Reject messages not coming from the OAuth receiver window.
if sender and sender.tab
unless sender.tab.url.substring(0, @receiverUrl.length) is @receiverUrl
return
# Reject improperly formatted messages.
return unless message.dropbox_oauth_receiver_href
receiverHref = message.dropbox_oauth_receiver_href
if @locationStateParam(receiverHref) is stateParam
stateParam = false # Avoid having this matched in the future.
chrome.tabs.remove oauthTab.id if oauthTab
chrome.runtime.onMessage.removeListener listener
callback Dropbox.Util.Oauth.queryParamsFromUrl(receiverHref)
chrome.runtime.onMessage.addListener listener
chrome.tabs.create url: authUrl, active: true, pinned: false, (tab) ->
oauthTab = tab
# Communicates with the driver from the OAuth receiver page.
#
# The easiest way for a Chrome extension to keep up to date with dropbox.js
# is to set up a popup receiver page that loads dropbox.js and calls this
# method. This guarantees that the code used to communicate between the popup
# receiver page and {Dropbox.AuthDriver.ChromeExtension#doAuthorize} stays up
# to date as dropbox.js is updated.
@oauthReceiver: ->
window.addEventListener 'load', ->
pageUrl = window.location.href
window.location.hash = '' # Remove the token from the browser history.
chrome.runtime.sendMessage dropbox_oauth_receiver_href: pageUrl
window.close() if window.close