|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 Cu.import("resource://gre/modules/Log.jsm"); |
|
5 Cu.import("resource://services-sync/constants.js"); |
|
6 Cu.import("resource://services-sync/keys.js"); |
|
7 Cu.import("resource://services-sync/engines/tabs.js"); |
|
8 Cu.import("resource://services-sync/engines.js"); |
|
9 Cu.import("resource://services-sync/record.js"); |
|
10 Cu.import("resource://services-sync/service.js"); |
|
11 Cu.import("resource://services-sync/util.js"); |
|
12 Cu.import("resource://testing-common/services/sync/utils.js"); |
|
13 |
|
14 Service.engineManager.register(TabEngine); |
|
15 |
|
16 add_test(function v4_upgrade() { |
|
17 let passphrase = "abcdeabcdeabcdeabcdeabcdea"; |
|
18 |
|
19 let clients = new ServerCollection(); |
|
20 let meta_global = new ServerWBO('global'); |
|
21 |
|
22 // Tracking info/collections. |
|
23 let collectionsHelper = track_collections_helper(); |
|
24 let upd = collectionsHelper.with_updated_collection; |
|
25 let collections = collectionsHelper.collections; |
|
26 |
|
27 let keysWBO = new ServerWBO("keys"); |
|
28 let server = httpd_setup({ |
|
29 // Special. |
|
30 "/1.1/johndoe/info/collections": collectionsHelper.handler, |
|
31 "/1.1/johndoe/storage/crypto/keys": upd("crypto", keysWBO.handler()), |
|
32 "/1.1/johndoe/storage/meta/global": upd("meta", meta_global.handler()), |
|
33 |
|
34 // Track modified times. |
|
35 "/1.1/johndoe/storage/clients": upd("clients", clients.handler()), |
|
36 "/1.1/johndoe/storage/tabs": upd("tabs", new ServerCollection().handler()), |
|
37 |
|
38 // Just so we don't get 404s in the logs. |
|
39 "/1.1/johndoe/storage/bookmarks": new ServerCollection().handler(), |
|
40 "/1.1/johndoe/storage/forms": new ServerCollection().handler(), |
|
41 "/1.1/johndoe/storage/history": new ServerCollection().handler(), |
|
42 "/1.1/johndoe/storage/passwords": new ServerCollection().handler(), |
|
43 "/1.1/johndoe/storage/prefs": new ServerCollection().handler() |
|
44 }); |
|
45 |
|
46 ensureLegacyIdentityManager(); |
|
47 |
|
48 try { |
|
49 |
|
50 _("Set up some tabs."); |
|
51 let myTabs = |
|
52 {windows: [{tabs: [{index: 1, |
|
53 entries: [{ |
|
54 url: "http://foo.com/", |
|
55 title: "Title" |
|
56 }], |
|
57 attributes: { |
|
58 image: "image" |
|
59 } |
|
60 }]}]}; |
|
61 delete Svc.Session; |
|
62 Svc.Session = { |
|
63 getBrowserState: function () JSON.stringify(myTabs) |
|
64 }; |
|
65 |
|
66 Service.status.resetSync(); |
|
67 |
|
68 _("Logging in."); |
|
69 Service.serverURL = server.baseURI; |
|
70 |
|
71 Service.login("johndoe", "ilovejane", passphrase); |
|
72 do_check_true(Service.isLoggedIn); |
|
73 Service.verifyAndFetchSymmetricKeys(); |
|
74 do_check_true(Service._remoteSetup()); |
|
75 |
|
76 function test_out_of_date() { |
|
77 _("Old meta/global: " + JSON.stringify(meta_global)); |
|
78 meta_global.payload = JSON.stringify({"syncID": "foooooooooooooooooooooooooo", |
|
79 "storageVersion": STORAGE_VERSION + 1}); |
|
80 collections.meta = Date.now() / 1000; |
|
81 _("New meta/global: " + JSON.stringify(meta_global)); |
|
82 Service.recordManager.set(Service.metaURL, meta_global); |
|
83 try { |
|
84 Service.sync(); |
|
85 } |
|
86 catch (ex) { |
|
87 } |
|
88 do_check_eq(Service.status.sync, VERSION_OUT_OF_DATE); |
|
89 } |
|
90 |
|
91 // See what happens when we bump the storage version. |
|
92 _("Syncing after server has been upgraded."); |
|
93 test_out_of_date(); |
|
94 |
|
95 // Same should happen after a wipe. |
|
96 _("Syncing after server has been upgraded and wiped."); |
|
97 Service.wipeServer(); |
|
98 test_out_of_date(); |
|
99 |
|
100 // Now's a great time to test what happens when keys get replaced. |
|
101 _("Syncing afresh..."); |
|
102 Service.logout(); |
|
103 Service.collectionKeys.clear(); |
|
104 Service.serverURL = server.baseURI; |
|
105 meta_global.payload = JSON.stringify({"syncID": "foooooooooooooobbbbbbbbbbbb", |
|
106 "storageVersion": STORAGE_VERSION}); |
|
107 collections.meta = Date.now() / 1000; |
|
108 Service.recordManager.set(Service.metaURL, meta_global); |
|
109 Service.login("johndoe", "ilovejane", passphrase); |
|
110 do_check_true(Service.isLoggedIn); |
|
111 Service.sync(); |
|
112 do_check_true(Service.isLoggedIn); |
|
113 |
|
114 let serverDecrypted; |
|
115 let serverKeys; |
|
116 let serverResp; |
|
117 |
|
118 |
|
119 function retrieve_server_default() { |
|
120 serverKeys = serverResp = serverDecrypted = null; |
|
121 |
|
122 serverKeys = new CryptoWrapper("crypto", "keys"); |
|
123 serverResp = serverKeys.fetch(Service.resource(Service.cryptoKeysURL)).response; |
|
124 do_check_true(serverResp.success); |
|
125 |
|
126 serverDecrypted = serverKeys.decrypt(Service.identity.syncKeyBundle); |
|
127 _("Retrieved WBO: " + JSON.stringify(serverDecrypted)); |
|
128 _("serverKeys: " + JSON.stringify(serverKeys)); |
|
129 |
|
130 return serverDecrypted.default; |
|
131 } |
|
132 |
|
133 function retrieve_and_compare_default(should_succeed) { |
|
134 let serverDefault = retrieve_server_default(); |
|
135 let localDefault = Service.collectionKeys.keyForCollection().keyPairB64; |
|
136 |
|
137 _("Retrieved keyBundle: " + JSON.stringify(serverDefault)); |
|
138 _("Local keyBundle: " + JSON.stringify(localDefault)); |
|
139 |
|
140 if (should_succeed) |
|
141 do_check_eq(JSON.stringify(serverDefault), JSON.stringify(localDefault)); |
|
142 else |
|
143 do_check_neq(JSON.stringify(serverDefault), JSON.stringify(localDefault)); |
|
144 } |
|
145 |
|
146 // Uses the objects set above. |
|
147 function set_server_keys(pair) { |
|
148 serverDecrypted.default = pair; |
|
149 serverKeys.cleartext = serverDecrypted; |
|
150 serverKeys.encrypt(Service.identity.syncKeyBundle); |
|
151 serverKeys.upload(Service.resource(Service.cryptoKeysURL)); |
|
152 } |
|
153 |
|
154 _("Checking we have the latest keys."); |
|
155 retrieve_and_compare_default(true); |
|
156 |
|
157 _("Update keys on server."); |
|
158 set_server_keys(["KaaaaaaaaaaaHAtfmuRY0XEJ7LXfFuqvF7opFdBD/MY=", |
|
159 "aaaaaaaaaaaapxMO6TEWtLIOv9dj6kBAJdzhWDkkkis="]); |
|
160 |
|
161 _("Checking that we no longer have the latest keys."); |
|
162 retrieve_and_compare_default(false); |
|
163 |
|
164 _("Indeed, they're what we set them to..."); |
|
165 do_check_eq("KaaaaaaaaaaaHAtfmuRY0XEJ7LXfFuqvF7opFdBD/MY=", |
|
166 retrieve_server_default()[0]); |
|
167 |
|
168 _("Sync. Should download changed keys automatically."); |
|
169 let oldClientsModified = collections.clients; |
|
170 let oldTabsModified = collections.tabs; |
|
171 |
|
172 Service.login("johndoe", "ilovejane", passphrase); |
|
173 Service.sync(); |
|
174 _("New key should have forced upload of data."); |
|
175 _("Tabs: " + oldTabsModified + " < " + collections.tabs); |
|
176 _("Clients: " + oldClientsModified + " < " + collections.clients); |
|
177 do_check_true(collections.clients > oldClientsModified); |
|
178 do_check_true(collections.tabs > oldTabsModified); |
|
179 |
|
180 _("... and keys will now match."); |
|
181 retrieve_and_compare_default(true); |
|
182 |
|
183 // Clean up. |
|
184 Service.startOver(); |
|
185 |
|
186 } finally { |
|
187 Svc.Prefs.resetBranch(""); |
|
188 server.stop(run_next_test); |
|
189 } |
|
190 }); |
|
191 |
|
192 add_test(function v5_upgrade() { |
|
193 let passphrase = "abcdeabcdeabcdeabcdeabcdea"; |
|
194 |
|
195 // Tracking info/collections. |
|
196 let collectionsHelper = track_collections_helper(); |
|
197 let upd = collectionsHelper.with_updated_collection; |
|
198 let collections = collectionsHelper.collections; |
|
199 |
|
200 let keysWBO = new ServerWBO("keys"); |
|
201 let bulkWBO = new ServerWBO("bulk"); |
|
202 let clients = new ServerCollection(); |
|
203 let meta_global = new ServerWBO('global'); |
|
204 |
|
205 let server = httpd_setup({ |
|
206 // Special. |
|
207 "/1.1/johndoe/storage/meta/global": upd("meta", meta_global.handler()), |
|
208 "/1.1/johndoe/info/collections": collectionsHelper.handler, |
|
209 "/1.1/johndoe/storage/crypto/keys": upd("crypto", keysWBO.handler()), |
|
210 "/1.1/johndoe/storage/crypto/bulk": upd("crypto", bulkWBO.handler()), |
|
211 |
|
212 // Track modified times. |
|
213 "/1.1/johndoe/storage/clients": upd("clients", clients.handler()), |
|
214 "/1.1/johndoe/storage/tabs": upd("tabs", new ServerCollection().handler()), |
|
215 }); |
|
216 |
|
217 try { |
|
218 |
|
219 _("Set up some tabs."); |
|
220 let myTabs = |
|
221 {windows: [{tabs: [{index: 1, |
|
222 entries: [{ |
|
223 url: "http://foo.com/", |
|
224 title: "Title" |
|
225 }], |
|
226 attributes: { |
|
227 image: "image" |
|
228 } |
|
229 }]}]}; |
|
230 delete Svc.Session; |
|
231 Svc.Session = { |
|
232 getBrowserState: function () JSON.stringify(myTabs) |
|
233 }; |
|
234 |
|
235 Service.status.resetSync(); |
|
236 |
|
237 setBasicCredentials("johndoe", "ilovejane", passphrase); |
|
238 Service.serverURL = server.baseURI + "/"; |
|
239 Service.clusterURL = server.baseURI + "/"; |
|
240 |
|
241 // Test an upgrade where the contents of the server would cause us to error |
|
242 // -- keys decrypted with a different sync key, for example. |
|
243 _("Testing v4 -> v5 (or similar) upgrade."); |
|
244 function update_server_keys(syncKeyBundle, wboName, collWBO) { |
|
245 generateNewKeys(Service.collectionKeys); |
|
246 serverKeys = Service.collectionKeys.asWBO("crypto", wboName); |
|
247 serverKeys.encrypt(syncKeyBundle); |
|
248 let res = Service.resource(Service.storageURL + collWBO); |
|
249 do_check_true(serverKeys.upload(res).success); |
|
250 } |
|
251 |
|
252 _("Bumping version."); |
|
253 // Bump version on the server. |
|
254 let m = new WBORecord("meta", "global"); |
|
255 m.payload = {"syncID": "foooooooooooooooooooooooooo", |
|
256 "storageVersion": STORAGE_VERSION + 1}; |
|
257 m.upload(Service.resource(Service.metaURL)); |
|
258 |
|
259 _("New meta/global: " + JSON.stringify(meta_global)); |
|
260 |
|
261 // Fill the keys with bad data. |
|
262 let badKeys = new SyncKeyBundle("foobar", "aaaaaaaaaaaaaaaaaaaaaaaaaa"); |
|
263 update_server_keys(badKeys, "keys", "crypto/keys"); // v4 |
|
264 update_server_keys(badKeys, "bulk", "crypto/bulk"); // v5 |
|
265 |
|
266 _("Generating new keys."); |
|
267 generateNewKeys(Service.collectionKeys); |
|
268 |
|
269 // Now sync and see what happens. It should be a version fail, not a crypto |
|
270 // fail. |
|
271 |
|
272 _("Logging in."); |
|
273 try { |
|
274 Service.login("johndoe", "ilovejane", passphrase); |
|
275 } |
|
276 catch (e) { |
|
277 _("Exception: " + e); |
|
278 } |
|
279 _("Status: " + Service.status); |
|
280 do_check_false(Service.isLoggedIn); |
|
281 do_check_eq(VERSION_OUT_OF_DATE, Service.status.sync); |
|
282 |
|
283 // Clean up. |
|
284 Service.startOver(); |
|
285 |
|
286 } finally { |
|
287 Svc.Prefs.resetBranch(""); |
|
288 server.stop(run_next_test); |
|
289 } |
|
290 }); |
|
291 |
|
292 function run_test() { |
|
293 let logger = Log.repository.rootLogger; |
|
294 Log.repository.rootLogger.addAppender(new Log.DumpAppender()); |
|
295 |
|
296 run_next_test(); |
|
297 } |