dom/contacts/tests/test_migration_chrome.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* global
michael@0 2 sendAsyncMessage,
michael@0 3 addMessageListener,
michael@0 4 indexedDB
michael@0 5 */
michael@0 6 "use strict";
michael@0 7
michael@0 8 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
michael@0 9
michael@0 10 let imports = {};
michael@0 11
michael@0 12 Cu.import("resource://gre/modules/ContactDB.jsm", imports);
michael@0 13 Cu.import("resource://gre/modules/ContactService.jsm", imports);
michael@0 14 Cu.import("resource://gre/modules/Promise.jsm", imports);
michael@0 15 Cu.importGlobalProperties(["indexedDB"]);
michael@0 16
michael@0 17 const {
michael@0 18 STORE_NAME,
michael@0 19 SAVED_GETALL_STORE_NAME,
michael@0 20 REVISION_STORE,
michael@0 21 DB_NAME,
michael@0 22 ContactService,
michael@0 23 } = imports;
michael@0 24 // |const| will not work because
michael@0 25 // it will make the Promise object immutable before assigning.
michael@0 26 // Using Object.defineProperty() instead.
michael@0 27 Object.defineProperty(this, "Promise", {
michael@0 28 value: imports.Promise, writable: false, configurable: false
michael@0 29 });
michael@0 30
michael@0 31 let DEBUG = false;
michael@0 32 function debug(str) {
michael@0 33 if (DEBUG){
michael@0 34 dump("-*- TestMigrationChromeScript: " + str + "\n");
michael@0 35 }
michael@0 36 }
michael@0 37
michael@0 38 const DATA = {
michael@0 39 12: {
michael@0 40 SCHEMA: function createSchema12(db, transaction) {
michael@0 41 let objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
michael@0 42 objectStore.createIndex("familyName", "properties.familyName", { multiEntry: true });
michael@0 43 objectStore.createIndex("givenName", "properties.givenName", { multiEntry: true });
michael@0 44 objectStore.createIndex("familyNameLowerCase", "search.familyName", { multiEntry: true });
michael@0 45 objectStore.createIndex("givenNameLowerCase", "search.givenName", { multiEntry: true });
michael@0 46 objectStore.createIndex("telLowerCase", "search.tel", { multiEntry: true });
michael@0 47 objectStore.createIndex("emailLowerCase", "search.email", { multiEntry: true });
michael@0 48 objectStore.createIndex("tel", "search.exactTel", { multiEntry: true });
michael@0 49 objectStore.createIndex("category", "properties.category", { multiEntry: true });
michael@0 50 objectStore.createIndex("email", "search.email", { multiEntry: true });
michael@0 51 objectStore.createIndex("telMatch", "search.parsedTel", {multiEntry: true});
michael@0 52 db.createObjectStore(SAVED_GETALL_STORE_NAME);
michael@0 53 db.createObjectStore(REVISION_STORE).put(0, "revision");
michael@0 54 },
michael@0 55 BAD: [
michael@0 56 {
michael@0 57 // this contact is bad because its "name" property is not an array and
michael@0 58 // is the empty string (upgrade 16 to 17)
michael@0 59 "properties": {
michael@0 60 "name": "",
michael@0 61 "email": [],
michael@0 62 "url": [{
michael@0 63 "type": ["source"],
michael@0 64 "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
michael@0 65 }],
michael@0 66 "category": ["gmail"],
michael@0 67 "adr": [],
michael@0 68 "tel": [{
michael@0 69 "type": ["mobile"],
michael@0 70 "value": "+7 123 456-78-90"
michael@0 71 }],
michael@0 72 "sex": "undefined",
michael@0 73 "genderIdentity": "undefined"
michael@0 74 },
michael@0 75 "search": {
michael@0 76 "givenName": [],
michael@0 77 "familyName": [],
michael@0 78 "email": [],
michael@0 79 "category": ["gmail"],
michael@0 80 "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
michael@0 81 "4567890","567890","67890","7890","890","90","0","81234567890"],
michael@0 82 "exactTel": ["+71234567890"],
michael@0 83 "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
michael@0 84 },
michael@0 85 "updated": new Date("2013-07-27T16:47:40.974Z"),
michael@0 86 "published": new Date("2013-07-27T16:47:40.974Z"),
michael@0 87 "id": "bad-1"
michael@0 88 },
michael@0 89 {
michael@0 90 // This contact is bad because its "name" property is not an array
michael@0 91 // (upgrade 14 to 15)
michael@0 92 "properties": {
michael@0 93 "name": "name-bad-2",
michael@0 94 "email": [],
michael@0 95 "url": [{
michael@0 96 "type": ["source"],
michael@0 97 "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
michael@0 98 }],
michael@0 99 "category": ["gmail"],
michael@0 100 "adr": [],
michael@0 101 "tel": [{
michael@0 102 "type": ["mobile"],
michael@0 103 "value": "+7 123 456-78-90"
michael@0 104 }],
michael@0 105 "sex": "undefined",
michael@0 106 "genderIdentity": "undefined"
michael@0 107 },
michael@0 108 "search": {
michael@0 109 "givenName": [],
michael@0 110 "familyName": [],
michael@0 111 "email": [],
michael@0 112 "category": ["gmail"],
michael@0 113 "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
michael@0 114 "4567890","567890","67890","7890","890","90","0","81234567890"],
michael@0 115 "exactTel": ["+71234567890"],
michael@0 116 "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
michael@0 117 },
michael@0 118 "updated": new Date("2013-07-27T16:47:40.974Z"),
michael@0 119 "published": new Date("2013-07-27T16:47:40.974Z"),
michael@0 120 "id": "bad-2"
michael@0 121 },
michael@0 122 {
michael@0 123 // This contact is bad because its bday property is a String (upgrade 15
michael@0 124 // to 16), and its anniversary property is an empty string (upgrade 16
michael@0 125 // to 17)
michael@0 126 "properties": {
michael@0 127 "name": ["name-bad-3"],
michael@0 128 "email": [],
michael@0 129 "url": [{
michael@0 130 "type": ["source"],
michael@0 131 "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
michael@0 132 }],
michael@0 133 "category": ["gmail"],
michael@0 134 "adr": [],
michael@0 135 "tel": [{
michael@0 136 "type": ["mobile"],
michael@0 137 "value": "+7 123 456-78-90"
michael@0 138 }],
michael@0 139 "sex": "undefined",
michael@0 140 "genderIdentity": "undefined",
michael@0 141 "bday": "2013-07-27T16:47:40.974Z",
michael@0 142 "anniversary": ""
michael@0 143 },
michael@0 144 "search": {
michael@0 145 "givenName": [],
michael@0 146 "familyName": [],
michael@0 147 "email": [],
michael@0 148 "category": ["gmail"],
michael@0 149 "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
michael@0 150 "4567890","567890","67890","7890","890","90","0","81234567890"],
michael@0 151 "exactTel": ["+71234567890"],
michael@0 152 "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
michael@0 153 },
michael@0 154 "updated": new Date("2013-07-27T16:47:40.974Z"),
michael@0 155 "published": new Date("2013-07-27T16:47:40.974Z"),
michael@0 156 "id": "bad-3"
michael@0 157 },
michael@0 158 {
michael@0 159 // This contact is bad because its tel property has a tel.type null
michael@0 160 // value (upgrade 16 to 17), and email.type not array value (upgrade 14
michael@0 161 // to 15)
michael@0 162 "properties": {
michael@0 163 "name": ["name-bad-4"],
michael@0 164 "email": [{
michael@0 165 "value": "toto@toto.com",
michael@0 166 "type": "home"
michael@0 167 }],
michael@0 168 "url": [{
michael@0 169 "type": ["source"],
michael@0 170 "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
michael@0 171 }],
michael@0 172 "category": ["gmail"],
michael@0 173 "adr": [],
michael@0 174 "tel": [{
michael@0 175 "type": null,
michael@0 176 "value": "+7 123 456-78-90"
michael@0 177 }],
michael@0 178 "sex": "undefined",
michael@0 179 "genderIdentity": "undefined"
michael@0 180 },
michael@0 181 "search": {
michael@0 182 "givenName": [],
michael@0 183 "familyName": [],
michael@0 184 "email": [],
michael@0 185 "category": ["gmail"],
michael@0 186 "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
michael@0 187 "4567890","567890","67890","7890","890","90","0","81234567890"],
michael@0 188 "exactTel": ["+71234567890"],
michael@0 189 "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
michael@0 190 },
michael@0 191 "updated": new Date("2013-07-27T16:47:40.974Z"),
michael@0 192 "published": new Date("2013-07-27T16:47:40.974Z"),
michael@0 193 "id": "bad-4"
michael@0 194 }
michael@0 195 ],
michael@0 196 GOOD: [
michael@0 197 {
michael@0 198 "properties": {
michael@0 199 "name": ["name-good-1"],
michael@0 200 "email": [],
michael@0 201 "url": [{
michael@0 202 "type": ["source"],
michael@0 203 "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
michael@0 204 }],
michael@0 205 "category": ["gmail"],
michael@0 206 "adr": [],
michael@0 207 "tel": [{
michael@0 208 "type": ["mobile"],
michael@0 209 "value": "+7 123 456-78-90"
michael@0 210 }],
michael@0 211 "sex": "undefined",
michael@0 212 "genderIdentity": "undefined"
michael@0 213 },
michael@0 214 "search": {
michael@0 215 "givenName": [],
michael@0 216 "familyName": [],
michael@0 217 "email": [],
michael@0 218 "category": ["gmail"],
michael@0 219 "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
michael@0 220 "4567890","567890","67890","7890","890","90","0","81234567890"],
michael@0 221 "exactTel": ["+71234567890"],
michael@0 222 "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
michael@0 223 },
michael@0 224 "updated": new Date("2013-07-27T16:47:40.974Z"),
michael@0 225 "published": new Date("2013-07-27T16:47:40.974Z"),
michael@0 226 "id": "good-1"
michael@0 227 }
michael@0 228 ]
michael@0 229 }
michael@0 230 };
michael@0 231
michael@0 232 function DataManager(version) {
michael@0 233 if (!(version in DATA)) {
michael@0 234 throw new Error("Version " + version + " can't be found in our test datas.");
michael@0 235 }
michael@0 236
michael@0 237 this.version = version;
michael@0 238 this.data = DATA[version];
michael@0 239 }
michael@0 240
michael@0 241 DataManager.prototype = {
michael@0 242 open: function() {
michael@0 243 debug("opening for version " + this.version);
michael@0 244 var deferred = Promise.defer();
michael@0 245
michael@0 246 let req = indexedDB.open(DB_NAME, this.version);
michael@0 247 req.onupgradeneeded = function() {
michael@0 248 let db = req.result;
michael@0 249 let transaction = req.transaction;
michael@0 250 this.createSchema(db, transaction);
michael@0 251 this.addContacts(db, transaction);
michael@0 252 }.bind(this);
michael@0 253
michael@0 254 req.onsuccess = function() {
michael@0 255 debug("succeeded opening the db, let's close it now");
michael@0 256 req.result.close();
michael@0 257 deferred.resolve(this.contactsCount());
michael@0 258 }.bind(this);
michael@0 259
michael@0 260 req.onerror = function() {
michael@0 261 deferred.reject(this.error);
michael@0 262 };
michael@0 263
michael@0 264 return deferred.promise;
michael@0 265 },
michael@0 266
michael@0 267 createSchema: function(db, transaction) {
michael@0 268 debug("createSchema for version " + this.version);
michael@0 269 this.data.SCHEMA(db, transaction);
michael@0 270 },
michael@0 271
michael@0 272 addContacts: function(db, transaction) {
michael@0 273 debug("adding contacts for version " + this.version);
michael@0 274 var os = transaction.objectStore(STORE_NAME);
michael@0 275
michael@0 276 this.data.GOOD.forEach(function(contact) {
michael@0 277 os.put(contact);
michael@0 278 });
michael@0 279 this.data.BAD.forEach(function(contact) {
michael@0 280 os.put(contact);
michael@0 281 });
michael@0 282 },
michael@0 283
michael@0 284 contactsCount: function() {
michael@0 285 return this.data.BAD.length + this.data.GOOD.length;
michael@0 286 }
michael@0 287 };
michael@0 288
michael@0 289 DataManager.delete = function() {
michael@0 290 debug("Deleting the database");
michael@0 291 var deferred = Promise.defer();
michael@0 292
michael@0 293 /* forcibly close the db before deleting it */
michael@0 294 ContactService._db.close();
michael@0 295
michael@0 296 var req = indexedDB.deleteDatabase(DB_NAME);
michael@0 297 req.onsuccess = function() {
michael@0 298 debug("Successfully deleted!");
michael@0 299 deferred.resolve();
michael@0 300 };
michael@0 301
michael@0 302 req.onerror = function() {
michael@0 303 debug("Not deleted, error is " + this.error.name);
michael@0 304 deferred.reject(this.error);
michael@0 305 };
michael@0 306
michael@0 307 req.onblocked = function() {
michael@0 308 debug("Waiting for the current users");
michael@0 309 };
michael@0 310
michael@0 311 return deferred.promise;
michael@0 312 };
michael@0 313
michael@0 314 addMessageListener("createDB", function(version) {
michael@0 315 // Promises help handling gracefully exceptions
michael@0 316 Promise.resolve().then(function() {
michael@0 317 return new DataManager(version);
michael@0 318 }).then(function(manager) {
michael@0 319 return manager.open();
michael@0 320 }).then(function onSuccess(count) {
michael@0 321 sendAsyncMessage("createDB.success", count);
michael@0 322 }, function onError(err) {
michael@0 323 sendAsyncMessage("createDB.error", "Failed to create the DB: " +
michael@0 324 "(" + err.name + ") " + err.message);
michael@0 325 });
michael@0 326 });
michael@0 327
michael@0 328 addMessageListener("deleteDB", function() {
michael@0 329 Promise.resolve().then(
michael@0 330 DataManager.delete
michael@0 331 ).then(function onSuccess() {
michael@0 332 sendAsyncMessage("deleteDB.success");
michael@0 333 }, function onError(err) {
michael@0 334 sendAsyncMessage("deleteDB.error", "Failed to delete the DB:" + err.name);
michael@0 335 });
michael@0 336 });

mercurial