chrome_sync.js revision dc0f95d653279beabeb9817299e2902918ba123e
1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvar chrome = chrome || {};
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// TODO(akalin): Add mocking code for e.g. chrome.send() so that we
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// can test this without rebuilding chrome.
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync = chrome.sync || {};
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen(function () {
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// This Event class is a simplified version of the one from
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// event_bindings.js.
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction Event() {
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  this.listeners_ = [];
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
17dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenEvent.prototype.addListener = function(listener) {
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  this.listeners_.push(listener);
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
21dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenEvent.prototype.removeListener = function(listener) {
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  var i = this.findListener_(listener);
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (i == -1) {
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  this.listeners_.splice(i, 1);
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
29dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenEvent.prototype.hasListener = function(listener) {
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return this.findListener_(listener) > -1;
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
33dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenEvent.prototype.hasListeners = function(listener) {
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return this.listeners_.length > 0;
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Returns the index of the given listener, or -1 if not found.
38dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenEvent.prototype.findListener_ = function(listener) {
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (var i = 0; i < this.listeners_.length; i++) {
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (this.listeners_[i] == listener) {
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return i;
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return -1;
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Fires the event.  Called by the actual event callback.  Any
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// exceptions thrown by a listener are caught and logged.
49dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenEvent.prototype.dispatch_ = function() {
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  var args = Array.prototype.slice.call(arguments);
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (var i = 0; i < this.listeners_.length; i++) {
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    try {
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      this.listeners_[i].apply(null, args);
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } catch (e) {
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (e instanceof Error) {
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        // Non-standard, but useful.
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        console.error(e.stack);
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else {
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        console.error(e);
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Service events.
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onSyncServiceStateChanged = new Event();
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Notifier events.
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onSyncNotificationStateChange = new Event();
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onSyncIncomingNotification = new Event();
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Manager events.
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onChangesApplied = new Event();
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onChangesComplete = new Event();
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onSyncCycleCompleted = new Event();
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onAuthError = new Event();
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onUpdatedToken = new Event();
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onPassphraseRequired = new Event();
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onPassphraseAccepted = new Event();
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onInitializationComplete = new Event();
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onPaused = new Event();
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onResumed = new Event();
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onStopSyncingPermanently = new Event();
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onClearServerDataSucceeded = new Event();
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.onClearServerDataFailed = new Event();
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction AsyncFunction(name) {
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  this.name_ = name;
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  this.callbacks_ = [];
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Calls the function, assuming the last argument is a callback to be
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// called with the return value.
94dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAsyncFunction.prototype.call = function() {
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  var args = Array.prototype.slice.call(arguments);
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  this.callbacks_.push(args.pop());
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.send(this.name_, args);
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Handle a reply, assuming that messages are processed in FIFO order.
101dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAsyncFunction.prototype.handleReply = function() {
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  var args = Array.prototype.slice.call(arguments);
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Remove the callback before we call it since the callback may
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // throw.
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  var callback = this.callbacks_.shift();
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  callback.apply(null, args);
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Sync service functions.
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getAboutInfo_ = new AsyncFunction('getAboutInfo');
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getAboutInfo = function(callback) {
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getAboutInfo_.call(callback);
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Notification functions.
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getNotificationState_ =
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    new AsyncFunction('getNotificationState');
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getNotificationState = function(callback) {
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getNotificationState_.call(callback);
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Node lookup functions.
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getRootNode_ = new AsyncFunction('getRootNode');
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getRootNode = function(callback) {
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getRootNode_.call(callback);
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getNodeById_ = new AsyncFunction('getNodeById');
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenchrome.sync.getNodeById = function(id, callback) {
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getNodeById_.call(id, callback);
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen})();
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// TODO(akalin): Rewrite the C++ side to not need the handlers below.
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Sync service event handlers.
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onSyncServiceStateChanged() {
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onSyncServiceStateChanged.dispatch_();
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Notification event handlers.
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onSyncNotificationStateChange(notificationsEnabled) {
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onSyncNotificationStateChange.dispatch_(notificationsEnabled);
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onSyncIncomingNotification(changedTypes) {
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onSyncIncomingNotification.dispatch_(changedTypes);
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Sync manager event handlers.
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onChangesApplied(modelType, changes) {
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onChangesApplied.dispatch_(modelType, changes);
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onChangesComplete(modelType) {
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onChangesComplete.dispatch_(modelType);
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onSyncCycleCompleted(snapshot) {
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onSyncCycleCompleted.dispatch_(snapshot);
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onAuthError(authError) {
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onAuthError.dispatch_(authError);
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onUpdatedToken(token) {
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onUpdatedToken.dispatch_(token);
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onPassphraseRequired(forDecryption) {
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onPassphraseRequired.dispatch_(forDecryption);
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onPassphraseAccepted(bootstrapToken) {
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onPassphraseAccepted.dispatch_(bootstrapToken);
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onInitializationComplete() {
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onInitializationComplete.dispatch_();
185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onPaused() {
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onPaused.dispatch_();
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onResumed() {
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onResumed.dispatch_();
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onStopSyncingPermanently() {
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onStopSyncingPermanently.dispatch_();
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onClearServerDataSucceeded() {
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onClearServerDataSucceeded();
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onClearServerDataFailed() {
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.onClearServerDataFailed();
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Function reply handlers.
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onGetAboutInfoFinished(aboutInfo) {
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getAboutInfo_.handleReply(aboutInfo);
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onGetNotificationStateFinished(notificationState) {
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getNotificationState_.handleReply(notificationState);
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onGetRootNodeFinished(rootNode) {
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getRootNode_.handleReply(rootNode);
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction onGetNodeByIdFinished(node) {
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  chrome.sync.getNodeById_.handleReply(node);
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
224