forked from esconie/dropbox-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchrome.coffee
160 lines (146 loc) · 6.55 KB
/
chrome.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# 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