// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var chrome = chrome || {}; // TODO(akalin): Add mocking code for e.g. chrome.send() so that we // can test this without rebuilding chrome. chrome.sync = chrome.sync || {}; (function () { // This Event class is a simplified version of the one from // event_bindings.js. function Event() { this.listeners_ = []; } Event.prototype.addListener = function(listener) { this.listeners_.push(listener); }; Event.prototype.removeListener = function(listener) { var i = this.findListener_(listener); if (i == -1) { return; } this.listeners_.splice(i, 1); }; Event.prototype.hasListener = function(listener) { return this.findListener_(listener) > -1; }; Event.prototype.hasListeners = function(listener) { return this.listeners_.length > 0; }; // Returns the index of the given listener, or -1 if not found. Event.prototype.findListener_ = function(listener) { for (var i = 0; i < this.listeners_.length; i++) { if (this.listeners_[i] == listener) { return i; } } return -1; }; // Fires the event. Called by the actual event callback. Any // exceptions thrown by a listener are caught and logged. Event.prototype.dispatch_ = function() { var args = Array.prototype.slice.call(arguments); for (var i = 0; i < this.listeners_.length; i++) { try { this.listeners_[i].apply(null, args); } catch (e) { if (e instanceof Error) { // Non-standard, but useful. console.error(e.stack); } else { console.error(e); } } } }; // Service events. chrome.sync.onSyncServiceStateChanged = new Event(); // Notifier events. chrome.sync.onSyncNotificationStateChange = new Event(); chrome.sync.onSyncIncomingNotification = new Event(); // Manager events. chrome.sync.onChangesApplied = new Event(); chrome.sync.onChangesComplete = new Event(); chrome.sync.onSyncCycleCompleted = new Event(); chrome.sync.onAuthError = new Event(); chrome.sync.onUpdatedToken = new Event(); chrome.sync.onPassphraseRequired = new Event(); chrome.sync.onPassphraseAccepted = new Event(); chrome.sync.onEncryptionComplete = new Event(); chrome.sync.onMigrationNeededForTypes = new Event(); chrome.sync.onInitializationComplete = new Event(); chrome.sync.onPaused = new Event(); chrome.sync.onResumed = new Event(); chrome.sync.onStopSyncingPermanently = new Event(); chrome.sync.onClearServerDataSucceeded = new Event(); chrome.sync.onClearServerDataFailed = new Event(); function AsyncFunction(name) { this.name_ = name; this.callbacks_ = []; } // Calls the function, assuming the last argument is a callback to be // called with the return value. AsyncFunction.prototype.call = function() { var args = Array.prototype.slice.call(arguments); this.callbacks_.push(args.pop()); chrome.send(this.name_, args); } // Handle a reply, assuming that messages are processed in FIFO order. AsyncFunction.prototype.handleReply = function() { var args = Array.prototype.slice.call(arguments); // Remove the callback before we call it since the callback may // throw. var callback = this.callbacks_.shift(); callback.apply(null, args); } // Sync service functions. chrome.sync.getAboutInfo_ = new AsyncFunction('getAboutInfo'); chrome.sync.getAboutInfo = function(callback) { chrome.sync.getAboutInfo_.call(callback); } // Notification functions. chrome.sync.getNotificationState_ = new AsyncFunction('getNotificationState'); chrome.sync.getNotificationState = function(callback) { chrome.sync.getNotificationState_.call(callback); } chrome.sync.getNotificationInfo_ = new AsyncFunction('getNotificationInfo'); chrome.sync.getNotificationInfo = function(callback) { chrome.sync.getNotificationInfo_.call(callback); } // Node lookup functions. chrome.sync.getRootNode_ = new AsyncFunction('getRootNode'); chrome.sync.getRootNode = function(callback) { chrome.sync.getRootNode_.call(callback); } chrome.sync.getNodeById_ = new AsyncFunction('getNodeById'); chrome.sync.getNodeById = function(id, callback) { chrome.sync.getNodeById_.call(id, callback); } })(); // TODO(akalin): Rewrite the C++ side to not need the handlers below. // Sync service event handlers. function onSyncServiceStateChanged() { chrome.sync.onSyncServiceStateChanged.dispatch_(); } // Notification event handlers. function onSyncNotificationStateChange(notificationsEnabled) { chrome.sync.onSyncNotificationStateChange.dispatch_(notificationsEnabled); } function onSyncIncomingNotification(changedTypes) { chrome.sync.onSyncIncomingNotification.dispatch_(changedTypes); } // Sync manager event handlers. function onChangesApplied(modelType, changes) { chrome.sync.onChangesApplied.dispatch_(modelType, changes); } function onChangesComplete(modelType) { chrome.sync.onChangesComplete.dispatch_(modelType); } function onSyncCycleCompleted(snapshot) { chrome.sync.onSyncCycleCompleted.dispatch_(snapshot); } function onAuthError(authError) { chrome.sync.onAuthError.dispatch_(authError); } function onUpdatedToken(token) { chrome.sync.onUpdatedToken.dispatch_(token); } function onPassphraseRequired(forDecryption) { chrome.sync.onPassphraseRequired.dispatch_(forDecryption); } function onPassphraseAccepted(bootstrapToken) { chrome.sync.onPassphraseAccepted.dispatch_(bootstrapToken); } function onEncryptionComplete(encrypted_types) { chrome.sync.onEncryptionComplete.dispatch_(encrypted_types); } function onMigrationNeededForTypes(model_types) { chrome.sync.onMigrationNeededForTypes.dispatch_(model_types); } function onInitializationComplete() { chrome.sync.onInitializationComplete.dispatch_(); } function onPaused() { chrome.sync.onPaused.dispatch_(); } function onResumed() { chrome.sync.onResumed.dispatch_(); } function onStopSyncingPermanently() { chrome.sync.onStopSyncingPermanently.dispatch_(); } function onClearServerDataSucceeded() { chrome.sync.onClearServerDataSucceeded(); } function onClearServerDataFailed() { chrome.sync.onClearServerDataFailed(); } // Function reply handlers. function onGetAboutInfoFinished(aboutInfo) { chrome.sync.getAboutInfo_.handleReply(aboutInfo); } function onGetNotificationStateFinished(notificationState) { chrome.sync.getNotificationState_.handleReply(notificationState); } function onGetRootNodeFinished(rootNode) { chrome.sync.getRootNode_.handleReply(rootNode); } function onGetNodeByIdFinished(node) { chrome.sync.getNodeById_.handleReply(node); } function onGetNotificationInfoFinished(notificationInfo) { chrome.sync.getNotificationInfo_.handleReply(notificationInfo); }