ares-ide
Version:
A browser-based code editor and UI designer for Enyo 2 projects
219 lines (197 loc) • 8.48 kB
text/coffeescript
DropboxChromeOnMessage = null
DropboxChromeSendMessage = null
if chrome?
# v2 manifest APIs.
if chrome.runtime
if chrome.runtime.onMessage
DropboxChromeOnMessage = chrome.runtime.onMessage
if chrome.runtime.sendMessage
DropboxChromeSendMessage = (m) -> chrome.runtime.sendMessage m
# v1 manifest APIs.
if chrome.extension
if chrome.extension.onMessage
DropboxChromeOnMessage or= chrome.extension.onMessage
if chrome.extension.sendMessage
DropboxChromeSendMessage or= (m) -> chrome.extension.sendMessage m
# Apps that use the v2 manifest don't get messenging in Chrome 25.
unless DropboxChromeOnMessage
do ->
pageHack = (page) ->
if page.Dropbox
Dropbox.Drivers.Chrome::onMessage =
page.Dropbox.Drivers.Chrome.onMessage
Dropbox.Drivers.Chrome::sendMessage =
page.Dropbox.Drivers.Chrome.sendMessage
else
page.Dropbox = Dropbox
Dropbox.Drivers.Chrome::onMessage = new Dropbox.EventSource
Dropbox.Drivers.Chrome::sendMessage =
(m) -> Dropbox.Drivers.Chrome::onMessage.dispatch m
if chrome.extension and chrome.extension.getBackgroundPage
if page = chrome.extension.getBackgroundPage()
return pageHack(page)
if chrome.runtime and chrome.runtime.getBackgroundPage
return chrome.runtime.getBackgroundPage (page) -> pageHack page
# OAuth driver specialized for Chrome apps and extensions.
class Dropbox.Drivers.Chrome extends Dropbox.Drivers.BrowserBase
# @property {Chrome.Event<Object>, Dropbox.EventSource<Object>} fires
# non-cancelable events when Dropbox.Drivers.Chrome#sendMessage is called;
# the message is a parsed JSON object
onMessage: DropboxChromeOnMessage
# Sends a message across the Chrome extension / application.
#
# This causes Dropbox.Drivers.Chrome#onMessage to fire an event containing
# the message
#
# @param {Object} message an object that can be serialized to JSON
# @return unspecified; may vary across platforms and dropbox.js versions
sendMessage: DropboxChromeSendMessage
# Expans an URL relative to the Chrome extension / application root.
#
# @param {String} url a resource URL relative to the extension root
# @return {String} the absolute resource URL
expandUrl: (url) ->
if chrome.runtime and chrome.runtime.getURL
return chrome.runtime.getURL(url)
if chrome.extension and chrome.extension.getURL
return chrome.extension.getURL(url)
url
# @param {?Object} options the settings below
# @option {String} receiverPath the path of page that receives the /authorize
# redirect and performs the postMessage; 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'
@rememberUser = true
@useQuery = true
[@receiverUrl, @receiverUrl2] = @computeUrl @expandUrl(receiverPath)
@storageKey = "dropbox_js_#{@scope}_credentials"
# Saves token information when appropriate.
onAuthStateChange: (client, callback) ->
switch client.authState
when Dropbox.Client.RESET
@loadCredentials (credentials) =>
if credentials
if credentials.authState
# Stuck authentication process, reset.
return @forgetCredentials(callback)
client.setCredentials credentials
callback()
when Dropbox.Client.DONE
@storeCredentials client.credentials(), callback
when Dropbox.Client.SIGNED_OFF
@forgetCredentials callback
when Dropbox.Client.ERROR
@forgetCredentials callback
else
callback()
# Shows the authorization URL in a pop-up, waits for it to send a message.
doAuthorize: (authUrl, token, tokenSecret, callback) ->
if chrome.identity?.launchWebAuthFlow
# Apps V2 after the identity API hits stable?
chrome.identity.launchWebAuthFlow url: authUrl, interactive: true,
(redirectUrl) =>
if @locationToken(redirectUrl) is token
callback()
else if chrome.experimental?.identity?.launchWebAuthFlow
# Apps V2 with identity in experimental
chrome.experimental.identity.launchWebAuthFlow
url: authUrl, interactive: true, (redirectUrl) =>
if @locationToken(redirectUrl) is token
callback()
else
# Extensions and Apps V1.
window = handle: null
@listenForMessage token, window, callback
@openWindow authUrl, (handle) -> window.handle = handle
# Creates a popup window.
#
# @param {String} url the URL that will be loaded in the popup window
# @param {function(Object)} callback called with a handle that can be passed
# to Dropbox.Driver.Chrome#closeWindow
# @return {Dropbox.Driver.Chrome} this
openWindow: (url, callback) ->
if chrome.tabs and chrome.tabs.create
chrome.tabs.create url: url, active: true, pinned: false, (tab) ->
callback tab
return @
@
# Closes a window that was previously opened with openWindow.
#
# @param {Object} handle the object passed to an openWindow callback
closeWindow: (handle) ->
if chrome.tabs and chrome.tabs.remove and handle.id
chrome.tabs.remove handle.id
return @
if chrome.app and chrome.app.window and handle.close
handle.close()
return @
@
# URL of the redirect receiver page that messages the app / extension.
url: (token) ->
@receiverUrl + encodeURIComponent(token)
# Listens for a postMessage from a previously opened tab.
#
# @param {String} token the token string that must be received from the tab
# @param {Object} window a JavaScript object whose "handle" property is a
# window handle passed to the callback of a
# Dropbox.Driver.Chrome#openWindow call
# @param {function()} called when the received message matches the token
listenForMessage: (token, window, callback) ->
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
if @locationToken(message.dropbox_oauth_receiver_href) is token
@closeWindow window.handle if window.handle
@onMessage.removeListener listener
callback()
@onMessage.addListener listener
# Stores a Dropbox.Client's credentials to local storage.
#
# @private
# onAuthStateChange 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.Drivers.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 localStorage.
#
# @private
# onAuthStateChange calls this method during the authentication flow.
#
# @param {function(?Object)} callback supplied with the credentials object
# stored by a previous call to
# Dropbox.Drivers.BrowserBase#storeCredentials; null if no credentials were
# stored, or if the previously stored credentials were deleted
# @return {Dropbox.Drivers.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
# onAuthStateChange calls this method during the authentication flow.
#
# @param {function()} callback called after the credentials are deleted
# @return {Dropbox.Drivers.BrowserBase} this, for easy call chaining
forgetCredentials: (callback) ->
chrome.storage.local.remove @storageKey, callback
@
# Communicates with the driver from the OAuth receiver page.
@oauthReceiver: ->
window.addEventListener 'load', ->
driver = new Dropbox.Drivers.Chrome()
driver.sendMessage dropbox_oauth_receiver_href: window.location.href
window.close() if window.close