1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5var chrome = chrome || {}; 6 7/** 8 * Organizes all signin event listeners and asynchronous requests. 9 * This object has no public constructor. 10 * @type {Object} 11 */ 12chrome.signin = chrome.signin || {}; 13 14(function() { 15 16// TODO(vishwath): This function is identical to the one in sync_internals.js 17// Merge both if possible. 18// Accepts a DOM node and sets its highlighted attribute oldVal != newVal 19function highlightIfChanged(node, oldVal, newVal) { 20 var oldStr = oldVal.toString(); 21 var newStr = newVal.toString(); 22 if (oldStr != '' && oldStr != newStr) { 23 // Note the addListener function does not end up creating duplicate 24 // listeners. There can be only one listener per event at a time. 25 // Reference: https://developer.mozilla.org/en/DOM/element.addEventListener 26 node.addEventListener('webkitAnimationEnd', 27 function() { this.removeAttribute('highlighted'); }, 28 false); 29 node.setAttribute('highlighted', ''); 30 } 31} 32 33// Wraps highlightIfChanged for multiple conditions. 34function highlightIfAnyChanged(node, oldToNewValList) { 35 for (var i = 0; i < oldToNewValList.length; i++) 36 highlightIfChanged(node, oldToNewValList[i][0], oldToNewValList[i][1]); 37} 38 39function setClassFromValue(value) { 40 if (value == 0) 41 return 'zero'; 42 if (value == 'Successful') 43 return 'ok'; 44 45 return ''; 46} 47 48// Allow signin_index.html to access the functions above using the 49// corresponding chrome.signin.<method> calls. 50chrome.signin['highlightIfChanged'] = highlightIfChanged; 51chrome.signin['highlightIfAnyChanged'] = highlightIfAnyChanged; 52chrome.signin['setClassFromValue'] = setClassFromValue; 53 54// Simplified Event class, borrowed (ok, stolen) from chrome_sync.js 55function Event() { 56 this.listeners_ = []; 57} 58 59// Add a new listener to the list. 60Event.prototype.addListener = function(listener) { 61 this.listeners_.push(listener); 62}; 63 64// Remove a listener from the list. 65Event.prototype.removeListener = function(listener) { 66 var i = this.findListener_(listener); 67 if (i == -1) { 68 return; 69 } 70 this.listeners_.splice(i, 1); 71}; 72 73// Check if the listener has already been registered so we can prevent 74// duplicate registrations. 75Event.prototype.hasListener = function(listener) { 76 return this.findListener_(listener) > -1; 77}; 78 79// Are there any listeners registered yet? 80Event.prototype.hasListeners = function() { 81 return this.listeners_.length > 0; 82}; 83 84// Returns the index of the given listener, or -1 if not found. 85Event.prototype.findListener_ = function(listener) { 86 for (var i = 0; i < this.listeners_.length; i++) { 87 if (this.listeners_[i] == listener) { 88 return i; 89 } 90 } 91 return -1; 92}; 93 94// Fires the event. Called by the actual event callback. Any 95// exceptions thrown by a listener are caught and logged. 96Event.prototype.fire = function() { 97 var args = Array.prototype.slice.call(arguments); 98 for (var i = 0; i < this.listeners_.length; i++) { 99 try { 100 this.listeners_[i].apply(null, args); 101 } catch (e) { 102 if (e instanceof Error) { 103 // Non-standard, but useful. 104 console.error(e.stack); 105 } else { 106 console.error(e); 107 } 108 } 109 } 110}; 111 112// These are the events that will be registered. 113chrome.signin.events = { 114 'signin_manager': [ 115 'onSigninInfoChanged' 116 ] 117}; 118 119for (var eventType in chrome.signin.events) { 120 var events = chrome.signin.events[eventType]; 121 for (var i = 0; i < events.length; ++i) { 122 var event = events[i]; 123 chrome.signin[event] = new Event(); 124 } 125} 126 127// Creates functions that call into SigninInternalsUI. 128function makeSigninFunction(name) { 129 var callbacks = []; 130 131 // Calls the function, assuming the last argument is a callback to be 132 // called with the return value. 133 var fn = function() { 134 var args = Array.prototype.slice.call(arguments); 135 callbacks.push(args.pop()); 136 chrome.send(name, args); 137 }; 138 139 // Handle a reply, assuming that messages are processed in FIFO order. 140 // Called by SigninInternalsUI::HandleJsReply(). 141 fn.handleReply = function() { 142 var args = Array.prototype.slice.call(arguments); 143 // Remove the callback before we call it since the callback may 144 // throw. 145 var callback = callbacks.shift(); 146 callback.apply(null, args); 147 }; 148 149 return fn; 150} 151 152// The list of js functions that call into SigninInternalsUI 153var signinFunctions = [ 154 // Signin Summary Info 155 'getSigninInfo' 156]; 157 158for (var i = 0; i < signinFunctions.length; ++i) { 159 var signinFunction = signinFunctions[i]; 160 chrome.signin[signinFunction] = makeSigninFunction(signinFunction); 161} 162 163chrome.signin.internalsInfo = {}; 164 165// Replace the displayed values with the latest fetched ones. 166function refreshSigninInfo(signinInfo) { 167 chrome.signin.internalsInfo = signinInfo; 168 var internalsInfoDiv = $('signin-info'); 169 jstProcess(new JsEvalContext(signinInfo), internalsInfoDiv); 170 var tokenInfoDiv = $('token-info'); 171 jstProcess(new JsEvalContext(signinInfo), tokenInfoDiv); 172} 173 174// On load, do an initial refresh and register refreshSigninInfo to be invoked 175// whenever we get new signin information from SigninInternalsUI. 176function onLoad() { 177 chrome.signin.getSigninInfo(refreshSigninInfo); 178 179 chrome.signin.onSigninInfoChanged.addListener(function(info) { 180 refreshSigninInfo(info); 181 }); 182} 183 184document.addEventListener('DOMContentLoaded', onLoad, false); 185})(); 186