OLD | NEW |
(Empty) | |
| 1 /** |
| 2 * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this |
| 3 * source code is governed by a BSD-style license that can be found in the |
| 4 * LICENSE file. |
| 5 */ |
| 6 |
| 7 /** |
| 8 * Constructor - no need to invoke directly, call initBackgroundPage instead. |
| 9 * @constructor |
| 10 * @param {String} url_request_token The OAuth request token URL. |
| 11 * @param {String} url_auth_token The OAuth authorize token URL. |
| 12 * @param {String} url_access_token The OAuth access token URL. |
| 13 * @param {String} consumer_key The OAuth consumer key. |
| 14 * @param {String} consumer_secret The OAuth consumer secret. |
| 15 * @param {String} oauth_scope The OAuth scope parameter. |
| 16 * @param {Object} opt_args Optional arguments. Recognized parameters: |
| 17 * "app_name" {String} Name of the current application |
| 18 * "callback_page" {String} If you renamed chrome_ex_oauth.html, the name |
| 19 * this file was renamed to. |
| 20 */ |
| 21 function ChromeExOAuth(url_request_token, url_auth_token, url_access_token, |
| 22 consumer_key, consumer_secret, oauth_scope, opt_args) { |
| 23 this.url_request_token = url_request_token; |
| 24 this.url_auth_token = url_auth_token; |
| 25 this.url_access_token = url_access_token; |
| 26 this.consumer_key = consumer_key; |
| 27 this.consumer_secret = consumer_secret; |
| 28 this.oauth_scope = oauth_scope; |
| 29 this.app_name = opt_args && opt_args['app_name'] || |
| 30 "ChromeExOAuth Library"; |
| 31 this.key_token = "oauth_token"; |
| 32 this.key_token_secret = "oauth_token_secret"; |
| 33 this.callback_page = opt_args && opt_args['callback_page'] || |
| 34 "chrome_ex_oauth.html"; |
| 35 this.auth_params = {}; |
| 36 if (opt_args && opt_args['auth_params']) { |
| 37 for (key in opt_args['auth_params']) { |
| 38 if (opt_args['auth_params'].hasOwnProperty(key)) { |
| 39 this.auth_params[key] = opt_args['auth_params'][key]; |
| 40 } |
| 41 } |
| 42 } |
| 43 }; |
| 44 |
| 45 /******************************************************************************* |
| 46 * PUBLIC API METHODS |
| 47 * Call these from your background page. |
| 48 ******************************************************************************/ |
| 49 |
| 50 /** |
| 51 * Initializes the OAuth helper from the background page. You must call this |
| 52 * before attempting to make any OAuth calls. |
| 53 * @param {Object} oauth_config Configuration parameters in a JavaScript object. |
| 54 * The following parameters are recognized: |
| 55 * "request_url" {String} OAuth request token URL. |
| 56 * "authorize_url" {String} OAuth authorize token URL. |
| 57 * "access_url" {String} OAuth access token URL. |
| 58 * "consumer_key" {String} OAuth consumer key. |
| 59 * "consumer_secret" {String} OAuth consumer secret. |
| 60 * "scope" {String} OAuth access scope. |
| 61 * "app_name" {String} Application name. |
| 62 * "auth_params" {Object} Additional parameters to pass to the |
| 63 * Authorization token URL. For an example, 'hd', 'hl', 'btmpl': |
| 64 * http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth |
| 65 * @return {ChromeExOAuth} An initialized ChromeExOAuth object. |
| 66 */ |
| 67 ChromeExOAuth.initBackgroundPage = function(oauth_config) { |
| 68 window.chromeExOAuthConfig = oauth_config; |
| 69 window.chromeExOAuth = ChromeExOAuth.fromConfig(oauth_config); |
| 70 window.chromeExOAuthRedirectStarted = false; |
| 71 window.chromeExOAuthRequestingAccess = false; |
| 72 |
| 73 var url_match = chrome.extension.getURL(window.chromeExOAuth.callback_page); |
| 74 var tabs = {}; |
| 75 chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { |
| 76 if (changeInfo.url && |
| 77 changeInfo.url.substr(0, url_match.length) === url_match && |
| 78 changeInfo.url != tabs[tabId] && |
| 79 window.chromeExOAuthRequestingAccess == false) { |
| 80 chrome.tabs.create({ 'url' : changeInfo.url }, function(tab) { |
| 81 tabs[tab.id] = tab.url; |
| 82 chrome.tabs.remove(tabId); |
| 83 }); |
| 84 } |
| 85 }); |
| 86 |
| 87 return window.chromeExOAuth; |
| 88 }; |
| 89 |
| 90 /** |
| 91 * Authorizes the current user with the configued API. You must call this |
| 92 * before calling sendSignedRequest. |
| 93 * @param {Function} callback A function to call once an access token has |
| 94 * been obtained. This callback will be passed the following arguments: |
| 95 * token {String} The OAuth access token. |
| 96 * secret {String} The OAuth access token secret. |
| 97 */ |
| 98 ChromeExOAuth.prototype.authorize = function(callback) { |
| 99 if (this.hasToken()) { |
| 100 callback(this.getToken(), this.getTokenSecret()); |
| 101 } else { |
| 102 window.chromeExOAuthOnAuthorize = function(token, secret) { |
| 103 callback(token, secret); |
| 104 }; |
| 105 chrome.tabs.create({ 'url' :chrome.extension.getURL(this.callback_page) }); |
| 106 } |
| 107 }; |
| 108 |
| 109 /** |
| 110 * Clears any OAuth tokens stored for this configuration. Effectively a |
| 111 * "logout" of the configured OAuth API. |
| 112 */ |
| 113 ChromeExOAuth.prototype.clearTokens = function() { |
| 114 delete localStorage[this.key_token + encodeURI(this.oauth_scope)]; |
| 115 delete localStorage[this.key_token_secret + encodeURI(this.oauth_scope)]; |
| 116 }; |
| 117 |
| 118 /** |
| 119 * Returns whether a token is currently stored for this configuration. |
| 120 * Effectively a check to see whether the current user is "logged in" to |
| 121 * the configured OAuth API. |
| 122 * @return {Boolean} True if an access token exists. |
| 123 */ |
| 124 ChromeExOAuth.prototype.hasToken = function() { |
| 125 return !!this.getToken(); |
| 126 }; |
| 127 |
| 128 /** |
| 129 * Makes an OAuth-signed HTTP request with the currently authorized tokens. |
| 130 * @param {String} url The URL to send the request to. Querystring parameters |
| 131 * should be omitted. |
| 132 * @param {Function} callback A function to be called once the request is |
| 133 * completed. This callback will be passed the following arguments: |
| 134 * responseText {String} The text response. |
| 135 * xhr {XMLHttpRequest} The XMLHttpRequest object which was used to |
| 136 * send the request. Useful if you need to check response status |
| 137 * code, etc. |
| 138 * @param {Object} opt_params Additional parameters to configure the request. |
| 139 * The following parameters are accepted: |
| 140 * "method" {String} The HTTP method to use. Defaults to "GET". |
| 141 * "body" {String} A request body to send. Defaults to null. |
| 142 * "parameters" {Object} Query parameters to include in the request. |
| 143 * "headers" {Object} Additional headers to include in the request. |
| 144 */ |
| 145 ChromeExOAuth.prototype.sendSignedRequest = function(url, callback, |
| 146 opt_params) { |
| 147 var method = opt_params && opt_params['method'] || 'GET'; |
| 148 var body = opt_params && opt_params['body'] || null; |
| 149 var params = opt_params && opt_params['parameters'] || {}; |
| 150 var headers = opt_params && opt_params['headers'] || {}; |
| 151 |
| 152 var signedUrl = this.signURL(url, method, params); |
| 153 |
| 154 ChromeExOAuth.sendRequest(method, signedUrl, headers, body, function (xhr) { |
| 155 if (xhr.readyState == 4) { |
| 156 callback(xhr.responseText, xhr); |
| 157 } |
| 158 }); |
| 159 }; |
| 160 |
| 161 /** |
| 162 * Adds the required OAuth parameters to the given url and returns the |
| 163 * result. Useful if you need a signed url but don't want to make an XHR |
| 164 * request. |
| 165 * @param {String} method The http method to use. |
| 166 * @param {String} url The base url of the resource you are querying. |
| 167 * @param {Object} opt_params Query parameters to include in the request. |
| 168 * @return {String} The base url plus any query params plus any OAuth params. |
| 169 */ |
| 170 ChromeExOAuth.prototype.signURL = function(url, method, opt_params) { |
| 171 var token = this.getToken(); |
| 172 var secret = this.getTokenSecret(); |
| 173 if (!token || !secret) { |
| 174 throw new Error("No oauth token or token secret"); |
| 175 } |
| 176 |
| 177 var params = opt_params || {}; |
| 178 |
| 179 var result = OAuthSimple().sign({ |
| 180 action : method, |
| 181 path : url, |
| 182 parameters : params, |
| 183 signatures: { |
| 184 consumer_key : this.consumer_key, |
| 185 shared_secret : this.consumer_secret, |
| 186 oauth_secret : secret, |
| 187 oauth_token: token |
| 188 } |
| 189 }); |
| 190 |
| 191 return result.signed_url; |
| 192 }; |
| 193 |
| 194 /** |
| 195 * Generates the Authorization header based on the oauth parameters. |
| 196 * @param {String} url The base url of the resource you are querying. |
| 197 * @param {Object} opt_params Query parameters to include in the request. |
| 198 * @return {String} An Authorization header containing the oauth_* params. |
| 199 */ |
| 200 ChromeExOAuth.prototype.getAuthorizationHeader = function(url, method, |
| 201 opt_params) { |
| 202 var token = this.getToken(); |
| 203 var secret = this.getTokenSecret(); |
| 204 if (!token || !secret) { |
| 205 throw new Error("No oauth token or token secret"); |
| 206 } |
| 207 |
| 208 var params = opt_params || {}; |
| 209 |
| 210 return OAuthSimple().getHeaderString({ |
| 211 action: method, |
| 212 path : url, |
| 213 parameters : params, |
| 214 signatures: { |
| 215 consumer_key : this.consumer_key, |
| 216 shared_secret : this.consumer_secret, |
| 217 oauth_secret : secret, |
| 218 oauth_token: token |
| 219 } |
| 220 }); |
| 221 }; |
| 222 |
| 223 /******************************************************************************* |
| 224 * PRIVATE API METHODS |
| 225 * Used by the library. There should be no need to call these methods directly. |
| 226 ******************************************************************************/ |
| 227 |
| 228 /** |
| 229 * Creates a new ChromeExOAuth object from the supplied configuration object. |
| 230 * @param {Object} oauth_config Configuration parameters in a JavaScript object. |
| 231 * The following parameters are recognized: |
| 232 * "request_url" {String} OAuth request token URL. |
| 233 * "authorize_url" {String} OAuth authorize token URL. |
| 234 * "access_url" {String} OAuth access token URL. |
| 235 * "consumer_key" {String} OAuth consumer key. |
| 236 * "consumer_secret" {String} OAuth consumer secret. |
| 237 * "scope" {String} OAuth access scope. |
| 238 * "app_name" {String} Application name. |
| 239 * "auth_params" {Object} Additional parameters to pass to the |
| 240 * Authorization token URL. For an example, 'hd', 'hl', 'btmpl': |
| 241 * http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth |
| 242 * @return {ChromeExOAuth} An initialized ChromeExOAuth object. |
| 243 */ |
| 244 ChromeExOAuth.fromConfig = function(oauth_config) { |
| 245 return new ChromeExOAuth( |
| 246 oauth_config['request_url'], |
| 247 oauth_config['authorize_url'], |
| 248 oauth_config['access_url'], |
| 249 oauth_config['consumer_key'], |
| 250 oauth_config['consumer_secret'], |
| 251 oauth_config['scope'], |
| 252 { |
| 253 'app_name' : oauth_config['app_name'], |
| 254 'auth_params' : oauth_config['auth_params'] |
| 255 } |
| 256 ); |
| 257 }; |
| 258 |
| 259 /** |
| 260 * Initializes chrome_ex_oauth.html and redirects the page if needed to start |
| 261 * the OAuth flow. Once an access token is obtained, this function closes |
| 262 * chrome_ex_oauth.html. |
| 263 */ |
| 264 ChromeExOAuth.initCallbackPage = function() { |
| 265 var background_page = chrome.extension.getBackgroundPage(); |
| 266 var oauth_config = background_page.chromeExOAuthConfig; |
| 267 var oauth = ChromeExOAuth.fromConfig(oauth_config); |
| 268 background_page.chromeExOAuthRedirectStarted = true; |
| 269 oauth.initOAuthFlow(function (token, secret) { |
| 270 background_page.chromeExOAuthOnAuthorize(token, secret); |
| 271 background_page.chromeExOAuthRedirectStarted = false; |
| 272 chrome.tabs.getSelected(null, function (tab) { |
| 273 chrome.tabs.remove(tab.id); |
| 274 }); |
| 275 }); |
| 276 }; |
| 277 |
| 278 /** |
| 279 * Sends an HTTP request. Convenience wrapper for XMLHttpRequest calls. |
| 280 * @param {String} method The HTTP method to use. |
| 281 * @param {String} url The URL to send the request to. |
| 282 * @param {Object} headers Optional request headers in key/value format. |
| 283 * @param {String} body Optional body content. |
| 284 * @param {Function} callback Function to call when the XMLHttpRequest's |
| 285 * ready state changes. See documentation for XMLHttpRequest's |
| 286 * onreadystatechange handler for more information. |
| 287 */ |
| 288 ChromeExOAuth.sendRequest = function(method, url, headers, body, callback) { |
| 289 var xhr = new XMLHttpRequest(); |
| 290 xhr.onreadystatechange = function(data) { |
| 291 callback(xhr, data); |
| 292 } |
| 293 xhr.open(method, url, true); |
| 294 if (headers) { |
| 295 for (var header in headers) { |
| 296 if (headers.hasOwnProperty(header)) { |
| 297 xhr.setRequestHeader(header, headers[header]); |
| 298 } |
| 299 } |
| 300 } |
| 301 xhr.send(body); |
| 302 }; |
| 303 |
| 304 /** |
| 305 * Decodes a URL-encoded string into key/value pairs. |
| 306 * @param {String} encoded An URL-encoded string. |
| 307 * @return {Object} An object representing the decoded key/value pairs found |
| 308 * in the encoded string. |
| 309 */ |
| 310 ChromeExOAuth.formDecode = function(encoded) { |
| 311 var params = encoded.split("&"); |
| 312 var decoded = {}; |
| 313 for (var i = 0, param; param = params[i]; i++) { |
| 314 var keyval = param.split("="); |
| 315 if (keyval.length == 2) { |
| 316 var key = ChromeExOAuth.fromRfc3986(keyval[0]); |
| 317 var val = ChromeExOAuth.fromRfc3986(keyval[1]); |
| 318 decoded[key] = val; |
| 319 } |
| 320 } |
| 321 return decoded; |
| 322 }; |
| 323 |
| 324 /** |
| 325 * Returns the current window's querystring decoded into key/value pairs. |
| 326 * @return {Object} A object representing any key/value pairs found in the |
| 327 * current window's querystring. |
| 328 */ |
| 329 ChromeExOAuth.getQueryStringParams = function() { |
| 330 var urlparts = window.location.href.split("?"); |
| 331 if (urlparts.length >= 2) { |
| 332 var querystring = urlparts.slice(1).join("?"); |
| 333 return ChromeExOAuth.formDecode(querystring); |
| 334 } |
| 335 return {}; |
| 336 }; |
| 337 |
| 338 /** |
| 339 * Binds a function call to a specific object. This function will also take |
| 340 * a variable number of additional arguments which will be prepended to the |
| 341 * arguments passed to the bound function when it is called. |
| 342 * @param {Function} func The function to bind. |
| 343 * @param {Object} obj The object to bind to the function's "this". |
| 344 * @return {Function} A closure that will call the bound function. |
| 345 */ |
| 346 ChromeExOAuth.bind = function(func, obj) { |
| 347 var newargs = Array.prototype.slice.call(arguments).slice(2); |
| 348 return function() { |
| 349 var combinedargs = newargs.concat(Array.prototype.slice.call(arguments)); |
| 350 func.apply(obj, combinedargs); |
| 351 }; |
| 352 }; |
| 353 |
| 354 /** |
| 355 * Encodes a value according to the RFC3986 specification. |
| 356 * @param {String} val The string to encode. |
| 357 */ |
| 358 ChromeExOAuth.toRfc3986 = function(val){ |
| 359 return encodeURIComponent(val) |
| 360 .replace(/\!/g, "%21") |
| 361 .replace(/\*/g, "%2A") |
| 362 .replace(/'/g, "%27") |
| 363 .replace(/\(/g, "%28") |
| 364 .replace(/\)/g, "%29"); |
| 365 }; |
| 366 |
| 367 /** |
| 368 * Decodes a string that has been encoded according to RFC3986. |
| 369 * @param {String} val The string to decode. |
| 370 */ |
| 371 ChromeExOAuth.fromRfc3986 = function(val){ |
| 372 var tmp = val |
| 373 .replace(/%21/g, "!") |
| 374 .replace(/%2A/g, "*") |
| 375 .replace(/%27/g, "'") |
| 376 .replace(/%28/g, "(") |
| 377 .replace(/%29/g, ")"); |
| 378 return decodeURIComponent(tmp); |
| 379 }; |
| 380 |
| 381 /** |
| 382 * Adds a key/value parameter to the supplied URL. |
| 383 * @param {String} url An URL which may or may not contain querystring values. |
| 384 * @param {String} key A key |
| 385 * @param {String} value A value |
| 386 * @return {String} The URL with URL-encoded versions of the key and value |
| 387 * appended, prefixing them with "&" or "?" as needed. |
| 388 */ |
| 389 ChromeExOAuth.addURLParam = function(url, key, value) { |
| 390 var sep = (url.indexOf('?') >= 0) ? "&" : "?"; |
| 391 return url + sep + |
| 392 ChromeExOAuth.toRfc3986(key) + "=" + ChromeExOAuth.toRfc3986(value); |
| 393 }; |
| 394 |
| 395 /** |
| 396 * Stores an OAuth token for the configured scope. |
| 397 * @param {String} token The token to store. |
| 398 */ |
| 399 ChromeExOAuth.prototype.setToken = function(token) { |
| 400 localStorage[this.key_token + encodeURI(this.oauth_scope)] = token; |
| 401 }; |
| 402 |
| 403 /** |
| 404 * Retrieves any stored token for the configured scope. |
| 405 * @return {String} The stored token. |
| 406 */ |
| 407 ChromeExOAuth.prototype.getToken = function() { |
| 408 return localStorage[this.key_token + encodeURI(this.oauth_scope)]; |
| 409 }; |
| 410 |
| 411 /** |
| 412 * Stores an OAuth token secret for the configured scope. |
| 413 * @param {String} secret The secret to store. |
| 414 */ |
| 415 ChromeExOAuth.prototype.setTokenSecret = function(secret) { |
| 416 localStorage[this.key_token_secret + encodeURI(this.oauth_scope)] = secret; |
| 417 }; |
| 418 |
| 419 /** |
| 420 * Retrieves any stored secret for the configured scope. |
| 421 * @return {String} The stored secret. |
| 422 */ |
| 423 ChromeExOAuth.prototype.getTokenSecret = function() { |
| 424 return localStorage[this.key_token_secret + encodeURI(this.oauth_scope)]; |
| 425 }; |
| 426 |
| 427 /** |
| 428 * Starts an OAuth authorization flow for the current page. If a token exists, |
| 429 * no redirect is needed and the supplied callback is called immediately. |
| 430 * If this method detects that a redirect has finished, it grabs the |
| 431 * appropriate OAuth parameters from the URL and attempts to retrieve an |
| 432 * access token. If no token exists and no redirect has happened, then |
| 433 * an access token is requested and the page is ultimately redirected. |
| 434 * @param {Function} callback The function to call once the flow has finished. |
| 435 * This callback will be passed the following arguments: |
| 436 * token {String} The OAuth access token. |
| 437 * secret {String} The OAuth access token secret. |
| 438 */ |
| 439 ChromeExOAuth.prototype.initOAuthFlow = function(callback) { |
| 440 if (!this.hasToken()) { |
| 441 var params = ChromeExOAuth.getQueryStringParams(); |
| 442 if (params['chromeexoauthcallback'] == 'true') { |
| 443 var oauth_token = params['oauth_token']; |
| 444 var oauth_verifier = params['oauth_verifier'] |
| 445 this.getAccessToken(oauth_token, oauth_verifier, callback); |
| 446 } else { |
| 447 var request_params = { |
| 448 'url_callback_param' : 'chromeexoauthcallback' |
| 449 } |
| 450 this.getRequestToken(function(url) { |
| 451 window.location.href = url; |
| 452 }, request_params); |
| 453 } |
| 454 } else { |
| 455 callback(this.getToken(), this.getTokenSecret()); |
| 456 } |
| 457 }; |
| 458 |
| 459 /** |
| 460 * Requests an OAuth request token. |
| 461 * @param {Function} callback Function to call once the authorize URL is |
| 462 * calculated. This callback will be passed the following arguments: |
| 463 * url {String} The URL the user must be redirected to in order to |
| 464 * approve the token. |
| 465 * @param {Object} opt_args Optional arguments. The following parameters |
| 466 * are accepted: |
| 467 * "url_callback" {String} The URL the OAuth provider will redirect to. |
| 468 * "url_callback_param" {String} A parameter to include in the callback |
| 469 * URL in order to indicate to this library that a redirect has |
| 470 * taken place. |
| 471 */ |
| 472 ChromeExOAuth.prototype.getRequestToken = function(callback, opt_args) { |
| 473 if (typeof callback !== "function") { |
| 474 throw new Error("Specified callback must be a function."); |
| 475 } |
| 476 var url = opt_args && opt_args['url_callback'] || |
| 477 window && window.top && window.top.location && |
| 478 window.top.location.href; |
| 479 |
| 480 var url_param = opt_args && opt_args['url_callback_param'] || |
| 481 "chromeexoauthcallback"; |
| 482 var url_callback = ChromeExOAuth.addURLParam(url, url_param, "true"); |
| 483 |
| 484 var result = OAuthSimple().sign({ |
| 485 path : this.url_request_token, |
| 486 parameters: { |
| 487 "xoauth_displayname" : this.app_name, |
| 488 "scope" : this.oauth_scope, |
| 489 "oauth_callback" : url_callback |
| 490 }, |
| 491 signatures: { |
| 492 consumer_key : this.consumer_key, |
| 493 shared_secret : this.consumer_secret |
| 494 } |
| 495 }); |
| 496 var onToken = ChromeExOAuth.bind(this.onRequestToken, this, callback); |
| 497 ChromeExOAuth.sendRequest("GET", result.signed_url, null, null, onToken); |
| 498 }; |
| 499 |
| 500 /** |
| 501 * Called when a request token has been returned. Stores the request token |
| 502 * secret for later use and sends the authorization url to the supplied |
| 503 * callback (for redirecting the user). |
| 504 * @param {Function} callback Function to call once the authorize URL is |
| 505 * calculated. This callback will be passed the following arguments: |
| 506 * url {String} The URL the user must be redirected to in order to |
| 507 * approve the token. |
| 508 * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the |
| 509 * request token. |
| 510 */ |
| 511 ChromeExOAuth.prototype.onRequestToken = function(callback, xhr) { |
| 512 if (xhr.readyState == 4) { |
| 513 if (xhr.status == 200) { |
| 514 var params = ChromeExOAuth.formDecode(xhr.responseText); |
| 515 var token = params['oauth_token']; |
| 516 this.setTokenSecret(params['oauth_token_secret']); |
| 517 var url = ChromeExOAuth.addURLParam(this.url_auth_token, |
| 518 "oauth_token", token); |
| 519 for (var key in this.auth_params) { |
| 520 if (this.auth_params.hasOwnProperty(key)) { |
| 521 url = ChromeExOAuth.addURLParam(url, key, this.auth_params[key]); |
| 522 } |
| 523 } |
| 524 callback(url); |
| 525 } else { |
| 526 throw new Error("Fetching request token failed. Status " + xhr.status); |
| 527 } |
| 528 } |
| 529 }; |
| 530 |
| 531 /** |
| 532 * Requests an OAuth access token. |
| 533 * @param {String} oauth_token The OAuth request token. |
| 534 * @param {String} oauth_verifier The OAuth token verifier. |
| 535 * @param {Function} callback The function to call once the token is obtained. |
| 536 * This callback will be passed the following arguments: |
| 537 * token {String} The OAuth access token. |
| 538 * secret {String} The OAuth access token secret. |
| 539 */ |
| 540 ChromeExOAuth.prototype.getAccessToken = function(oauth_token, oauth_verifier, |
| 541 callback) { |
| 542 if (typeof callback !== "function") { |
| 543 throw new Error("Specified callback must be a function."); |
| 544 } |
| 545 var bg = chrome.extension.getBackgroundPage(); |
| 546 if (bg.chromeExOAuthRequestingAccess == false) { |
| 547 bg.chromeExOAuthRequestingAccess = true; |
| 548 |
| 549 var result = OAuthSimple().sign({ |
| 550 path : this.url_access_token, |
| 551 parameters: { |
| 552 "oauth_token" : oauth_token, |
| 553 "oauth_verifier" : oauth_verifier |
| 554 }, |
| 555 signatures: { |
| 556 consumer_key : this.consumer_key, |
| 557 shared_secret : this.consumer_secret, |
| 558 oauth_secret : this.getTokenSecret(this.oauth_scope) |
| 559 } |
| 560 }); |
| 561 |
| 562 var onToken = ChromeExOAuth.bind(this.onAccessToken, this, callback); |
| 563 ChromeExOAuth.sendRequest("GET", result.signed_url, null, null, onToken); |
| 564 } |
| 565 }; |
| 566 |
| 567 /** |
| 568 * Called when an access token has been returned. Stores the access token and |
| 569 * access token secret for later use and sends them to the supplied callback. |
| 570 * @param {Function} callback The function to call once the token is obtained. |
| 571 * This callback will be passed the following arguments: |
| 572 * token {String} The OAuth access token. |
| 573 * secret {String} The OAuth access token secret. |
| 574 * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the |
| 575 * access token. |
| 576 */ |
| 577 ChromeExOAuth.prototype.onAccessToken = function(callback, xhr) { |
| 578 if (xhr.readyState == 4) { |
| 579 var bg = chrome.extension.getBackgroundPage(); |
| 580 if (xhr.status == 200) { |
| 581 var params = ChromeExOAuth.formDecode(xhr.responseText); |
| 582 var token = params["oauth_token"]; |
| 583 var secret = params["oauth_token_secret"]; |
| 584 this.setToken(token); |
| 585 this.setTokenSecret(secret); |
| 586 bg.chromeExOAuthRequestingAccess = false; |
| 587 callback(token, secret); |
| 588 } else { |
| 589 bg.chromeExOAuthRequestingAccess = false; |
| 590 throw new Error("Fetching access token failed with status " + xhr.status); |
| 591 } |
| 592 } |
| 593 }; |
OLD | NEW |