Bug 921478 - Part 2: Convert test_contacts_upgrade.html to real chrome mochitest. r=bent
authorVendelin Ruzicka <vendo.ruzicka@gmail.com>
Tue, 19 Nov 2013 08:36:33 +0100
changeset 156387 ce8a25e53bdaa04d04e740428fdc7a50baaeae60
parent 156386 fc6579a5b551c5484602449c36fa8def2c36822d
child 156388 a9228868922465e2e268987b8ae461e3b2965e04
push id25678
push userryanvm@gmail.com
push dateWed, 20 Nov 2013 03:26:13 +0000
treeherdermozilla-central@4f993fa378eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs921478
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 921478 - Part 2: Convert test_contacts_upgrade.html to real chrome mochitest. r=bent
dom/contacts/tests/chrome.ini
dom/contacts/tests/test_contacts_upgrade.html
dom/contacts/tests/test_contacts_upgrade.xul
dom/datastore/DataStore.jsm
dom/datastore/DataStoreDB.jsm
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/test/unit/xpcshell.ini
--- a/dom/contacts/tests/chrome.ini
+++ b/dom/contacts/tests/chrome.ini
@@ -1,3 +1,3 @@
 [DEFAULT]
 
-[test_contacts_upgrade.html]
+[test_contacts_upgrade.xul]
rename from dom/contacts/tests/test_contacts_upgrade.html
rename to dom/contacts/tests/test_contacts_upgrade.xul
--- a/dom/contacts/tests/test_contacts_upgrade.html
+++ b/dom/contacts/tests/test_contacts_upgrade.xul
@@ -1,279 +1,279 @@
-<!DOCTYPE html>
-<html>
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=889239
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
 -->
-<head>
-  <title>Test for Bug 889239</title>
-  <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
 
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=889239">Mozilla Bug 889239</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-"use strict";
-
-var isAndroid = (navigator.userAgent.indexOf("Android") !== -1);
+<window title="Mozilla Bug 889239"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
-function checkStr(str1, str2, msg) {
-  if (str1 ^ str2) {
-    ok(false, "Expected both strings to be either present or absent");
-    return;
-  }
-  is(str1, str2, msg);
-}
+  <script type="application/javascript;version=1.7">
+  <![CDATA[
+  "use strict";
+
+  var isAndroid = (navigator.userAgent.indexOf("Android") !== -1);
 
-function checkStrArray(str1, str2, msg) {
-  // comparing /[null(,null)+]/ and undefined should pass
-  function nonNull(e) {
-    return e != null;
-  }
-  if ((Array.isArray(str1) && str1.filter(nonNull).length == 0 && str2 == undefined)
-     ||(Array.isArray(str2) && str2.filter(nonNull).length == 0 && str1 == undefined)) {
-    ok(true, msg);
-  } else if (str1) {
-    is(JSON.stringify(typeof str1 == "string" ? [str1] : str1), JSON.stringify(typeof str2 == "string" ? [str2] : str2), msg);
-  }
-}
-
-function checkAddress(adr1, adr2) {
-  if (adr1 ^ adr2) {
-    ok(false, "Expected both adrs to be either present or absent");
-    return;
+  function checkStr(str1, str2, msg) {
+    if (str1 ^ str2) {
+      ok(false, "Expected both strings to be either present or absent");
+      return;
+    }
+    is(str1, str2, msg);
   }
-  checkStrArray(adr1.type, adr2.type, "Same type");
-  checkStrArray(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
-  checkStrArray(adr1.locality, adr2.locality, "Same locality");
-  checkStrArray(adr1.region, adr2.region, "Same region");
-  checkStrArray(adr1.postalCode, adr2.postalCode, "Same postalCode");
-  checkStrArray(adr1.countryName, adr2.countryName, "Same countryName");
-  is(adr1.pref, adr2.pref, "Same pref");
-}
 
-function checkTel(tel1, tel2) {
-  if (tel1 ^ tel2) {
-    ok(false, "Expected both tels to be either present or absent");
-    return;
-  }
-  checkStrArray(tel1.type, tel2.type, "Same type");
-  checkStrArray(tel1.value, tel2.value, "Same value");
-  checkStrArray(tel1.carrier, tel2.carrier, "Same carrier");
-  is(tel1.pref, tel2.pref, "Same pref");
-}
-
-function checkField(field1, field2) {
-  if (field1 ^ field2) {
-    ok(false, "Expected both fields to be either present or absent");
-    return;
+  function checkStrArray(str1, str2, msg) {
+    // comparing /[null(,null)+]/ and undefined should pass
+    function nonNull(e) {
+      return e != null;
+    }
+    if ((Array.isArray(str1) && str1.filter(nonNull).length == 0 && str2 == undefined)
+       ||(Array.isArray(str2) && str2.filter(nonNull).length == 0 && str1 == undefined)) {
+      ok(true, msg);
+    } else if (str1) {
+      is(JSON.stringify(typeof str1 == "string" ? [str1] : str1), JSON.stringify(typeof str2 == "string" ? [str2] : str2), msg);
+    }
   }
-  checkStrArray(field1.type, field2.type, "Same type");
-  checkStrArray(field1.value, field2.value, "Same value");
-  is(field1.pref, field2.pref, "Same pref");
-}
-
-function checkDBContacts(dbContact1, dbContact2) {
-  let contact1 = dbContact1.properties;
-  let contact2 = dbContact2.properties;
 
-  checkStrArray(contact1.name, contact2.name, "Same name");
-  checkStrArray(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
-  checkStrArray(contact1.givenName, contact2.givenName, "Same givenName");
-  checkStrArray(contact1.additionalName, contact2.additionalName, "Same additionalName");
-  checkStrArray(contact1.familyName, contact2.familyName, "Same familyName");
-  checkStrArray(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
-  checkStrArray(contact1.nickname, contact2.nickname, "Same nickname");
-  checkStrArray(contact1.category, contact2.category, "Same category");
-  checkStrArray(contact1.org, contact2.org, "Same org");
-  checkStrArray(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
-  is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
-  checkStrArray(contact1.note, contact2.note, "Same note");
-  is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
-  checkStr(contact1.sex, contact2.sex, "Same sex");
-  checkStr(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
-  checkStrArray(contact1.key, contact2.key, "Same key");
+  function checkAddress(adr1, adr2) {
+    if (adr1 ^ adr2) {
+      ok(false, "Expected both adrs to be either present or absent");
+      return;
+    }
+    checkStrArray(adr1.type, adr2.type, "Same type");
+    checkStrArray(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
+    checkStrArray(adr1.locality, adr2.locality, "Same locality");
+    checkStrArray(adr1.region, adr2.region, "Same region");
+    checkStrArray(adr1.postalCode, adr2.postalCode, "Same postalCode");
+    checkStrArray(adr1.countryName, adr2.countryName, "Same countryName");
+    is(adr1.pref, adr2.pref, "Same pref");
+  }
 
-  is(contact1.email.length, contact2.email.length, "Same number of emails");
-  for (let i = 0; i < contact1.email.length; ++i) {
-    checkField(contact1.email[i], contact2.email[i]);
+  function checkTel(tel1, tel2) {
+    if (tel1 ^ tel2) {
+      ok(false, "Expected both tels to be either present or absent");
+      return;
+    }
+    checkStrArray(tel1.type, tel2.type, "Same type");
+    checkStrArray(tel1.value, tel2.value, "Same value");
+    checkStrArray(tel1.carrier, tel2.carrier, "Same carrier");
+    is(tel1.pref, tel2.pref, "Same pref");
   }
 
-  is(contact1.adr.length, contact2.adr.length, "Same number of adrs");
-  for (var i in contact1.adr) {
-    checkAddress(contact1.adr[i], contact2.adr[i]);
+  function checkField(field1, field2) {
+    if (field1 ^ field2) {
+      ok(false, "Expected both fields to be either present or absent");
+      return;
+    }
+    checkStrArray(field1.type, field2.type, "Same type");
+    checkStrArray(field1.value, field2.value, "Same value");
+    is(field1.pref, field2.pref, "Same pref");
   }
 
-  is(contact1.tel.length, contact2.tel.length, "Same number of tels");
-  for (var i in contact1.tel) {
-    checkTel(contact1.tel[i], contact2.tel[i]);
-  }
+  function checkDBContacts(dbContact1, dbContact2) {
+    let contact1 = dbContact1.properties;
+    let contact2 = dbContact2.properties;
+
+    checkStrArray(contact1.name, contact2.name, "Same name");
+    checkStrArray(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
+    checkStrArray(contact1.givenName, contact2.givenName, "Same givenName");
+    checkStrArray(contact1.additionalName, contact2.additionalName, "Same additionalName");
+    checkStrArray(contact1.familyName, contact2.familyName, "Same familyName");
+    checkStrArray(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
+    checkStrArray(contact1.nickname, contact2.nickname, "Same nickname");
+    checkStrArray(contact1.category, contact2.category, "Same category");
+    checkStrArray(contact1.org, contact2.org, "Same org");
+    checkStrArray(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
+    is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
+    checkStrArray(contact1.note, contact2.note, "Same note");
+    is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
+    checkStr(contact1.sex, contact2.sex, "Same sex");
+    checkStr(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
+    checkStrArray(contact1.key, contact2.key, "Same key");
+
+    is(contact1.email.length, contact2.email.length, "Same number of emails");
+    for (let i = 0; i < contact1.email.length; ++i) {
+      checkField(contact1.email[i], contact2.email[i]);
+    }
 
-  is(contact1.url.length, contact2.url.length, "Same number of urls");
-  for (var i in contact1.url) {
-    checkField(contact1.url[i], contact2.url[i]);
-  }
+    is(contact1.adr.length, contact2.adr.length, "Same number of adrs");
+    for (var i in contact1.adr) {
+      checkAddress(contact1.adr[i], contact2.adr[i]);
+    }
+
+    is(contact1.tel.length, contact2.tel.length, "Same number of tels");
+    for (var i in contact1.tel) {
+      checkTel(contact1.tel[i], contact2.tel[i]);
+    }
+
+    is(contact1.url.length, contact2.url.length, "Same number of urls");
+    for (var i in contact1.url) {
+      checkField(contact1.url[i], contact2.url[i]);
+    }
 
-  is(contact1.impp.length, contact2.impp.length, "Same number of impps");
-  for (var i in contact1.impp) {
-    checkField(contact1.impp[i], contact2.impp[i]);
+    is(contact1.impp.length, contact2.impp.length, "Same number of impps");
+    for (var i in contact1.impp) {
+      checkField(contact1.impp[i], contact2.impp[i]);
+    }
+
+    // test search indexes
+    contact1 = dbContact1.search;
+    contact2 = dbContact2.search;
+    checkStrArray(contact1.category, contact2.category, "Same cateogry index");
+    checkStrArray(contact1.email, contact2.email, "Same email index");
+    checkStrArray(contact1.emailLowerCase, contact2.emailLowerCase, "Same emailLowerCase index");
+    checkStrArray(contact1.familyName, contact2.familyName, "Same familyName index");
+    checkStrArray(contact1.familyNameLowerCase, contact2.familyNameLowerCase, "Same familyNameLowerCase index");
+    checkStrArray(contact1.givenName, contact2.givenName, "Same givenName index");
+    checkStrArray(contact1.givenNameLowerCase, contact2.givenNameLowerCase, "Same givenNameLowerCase index");
+    checkStrArray(contact1.name, contact2.name, "Same name index");
+    checkStrArray(contact1.tel, contact2.tel, "Same tel index");
+    checkStrArray(contact1.telLowerCase, contact2.telLowerCase, "Same telLowerCase index");
+    checkStrArray(contact1.telMatch, contact2.telMatch, "Same telMatch index");
   }
 
-  // test search indexes
-  contact1 = dbContact1.search;
-  contact2 = dbContact2.search;
-  checkStrArray(contact1.category, contact2.category, "Same cateogry index");
-  checkStrArray(contact1.email, contact2.email, "Same email index");
-  checkStrArray(contact1.emailLowerCase, contact2.emailLowerCase, "Same emailLowerCase index");
-  checkStrArray(contact1.familyName, contact2.familyName, "Same familyName index");
-  checkStrArray(contact1.familyNameLowerCase, contact2.familyNameLowerCase, "Same familyNameLowerCase index");
-  checkStrArray(contact1.givenName, contact2.givenName, "Same givenName index");
-  checkStrArray(contact1.givenNameLowerCase, contact2.givenNameLowerCase, "Same givenNameLowerCase index");
-  checkStrArray(contact1.name, contact2.name, "Same name index");
-  checkStrArray(contact1.tel, contact2.tel, "Same tel index");
-  checkStrArray(contact1.telLowerCase, contact2.telLowerCase, "Same telLowerCase index");
-  checkStrArray(contact1.telMatch, contact2.telMatch, "Same telMatch index");
-}
-
-function makeFailure(reason) {
-  return function() {
-    ok(false, reason);
-    SimpleTest.finish();
-  };
-};
-
-const {Cc, Ci, Cu} = SpecialPowers;
-Cu.import("resource://gre/modules/ContactDB.jsm", window);
-Cu.importGlobalProperties(["indexedDB"]);
-
-let cdb = new ContactDB();
-cdb.init();
-
-let CONTACT_PROPS = {
-  id: "ab74671e36be41b680f8f030e7e24ea2",
-  properties: {
-    name: ["Magnificentest foo bar the third"],
-    givenName: ["foo"],
-    familyName: ["bar"],
-    honorificPrefix: ["magnificentest"],
-    honorificSuffix: ["the third"],
-    additionalName: ["addl"],
-    nickname: ["foo"],
-    tel: [
-      {type: ["mobile"], value: "+12345678901", carrier: "ACME Telecommunications", pref: true},
-      {type: ["home", "custom"], value: "7932012346", pref: false},
-    ],
-    email: [{type: ["work"], value: "a@b.c"}, {value: "b@c.d", pref: true}],
-    adr: [
-      {
-        type: ["home"],
-        streetAddress: "street 1",
-        locality: "locality 1",
-        region: "region 1",
-        postalCode: "postal code 1",
-        countryName: "country 1",
-      }
-    ],
-    impp: [{type: ["aim"], value:"im1", pref: true}, {value: "im2"}],
-    org: ["org1", "org2"],
-    jobTitle: ["boss", "superboss"],
-    bday: new Date("1980, 12, 01"),
-    note: ["bla bla bla"],
-    category: ["cat1", "cat2"],
-    url: [{type: ["work", "work2"], value: "www.1.com", pref: true}, {value: "www2.com"}],
-    anniversary: new Date("2000, 12, 01"),
-    sex: "male",
-    genderIdentity: "trisexual",
-    key: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAC4jAAAuIwF4pT92AAACrElEQVQozwXBTW8bRRgA4Hfemf1er7/iJI4Tq7VFlEZN1VZIlapy4MQBTkXcuSH+G/APKnGAAyCVCqmtCHETp64db5zdtdf7NbMzw/OQH378HkCZpmmapqYMy8yrNnadS6026HC/Z7k+SCkEBwKEEKaUQtQAmlDqrucH23nH4BRkJVRcwmod5gcn6LehFgCaEIIalFZaEcLCq73w355RdvY7nfGQGVTlmRXfqMlrUaSUMUQkhCISJIggKj3/YBHt7PRbpy+cwbF7dN/0vEqTMoo3s0tmGAAAoJAgImMq3xZ5WTPbHj4Mho8Nf+QcPtZBLxEkqeQ2WmklkRCtNdNaI1KpVCnqOC3j5ZK++4vnm6xSWZpzwQtRV2mOiBoRpEKtNQAQggjQcCwqinRxJeKlWW93dlqEsa2QRZbF85nWBAAZY4YUgl9fRJWKVuWgmhwHhpD1+ZrfVjAN867rMCne//rq7OuXjWaLCVHnOWHgFDwMw+Tvi09PdhtJXoVC7bWDIi8Lg8qyMk3rYjLzvJh2O30hwK6TpiG7zWDcck9GR17D9wxDcH7/oNtElRa1aZuLDJN4S7/87tssLVg0/eZs/3h0D5R89vR0v+1AVT0YHX31ZDy9uv7IeJrryeyu2+nS50/PqOXM5qt8Nf/jv08UwTfN27vkchldLpPf/nx/nqSz5sbzhkTYzLRppzNYre/ycrMIZwqsHdf96fd/Xr354AYBr/jESWhgGb6zVSuGrrQS1j4Zk8nc2Hs7frFb3Phc6+fOKDGLKOJTHvlj2u85N4t6vbw7OM4YRVquboPdsPNZ9eb8pvfAOf2iN4dN3EzWadnoO5JY19Oo0TYtw1t8TBqBR9v7wbOXROLWtZ3PH937+ZfXrb6BUHEbXL+FCIfDw92e5zebg8GR54r/AaMVcBxE6hgPAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDEyLTA3LTIxVDEwOjUzOjE5LTA0OjAwYyXbYgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMi0wNy0yMVQxMDo1MzoxOS0wNDowMBJ4Y94AAAARdEVYdGpwZWc6Y29sb3JzcGFjZQAyLHVVnwAAACB0RVh0anBlZzpzYW1wbGluZy1mYWN0b3IAMXgxLDF4MSwxeDHplfxwAAAAAElFTkSuQmCC"
-  }
-};
-
-function deleteDatabase(then) {
-  cdb.close();
-  let req = indexedDB.deleteDatabase(DB_NAME);
-  req.onsuccess = then;
-  req.onblocked = makeFailure("blocked");
-  req.onupgradeneeded = makeFailure("onupgradeneeded");
-  req.onerror = makeFailure("onerror");
-}
-
-function saveContact() {
-  // takes fast upgrade path
-  cdb.saveContact(CONTACT_PROPS,
-    function() {
-      ok(true, "Saved contact successfully");
-      next();
-    }
-  );
-}
-
-function getContact(callback) {
-  return function() {
-    let req = indexedDB.open(STORE_NAME, DB_VERSION);
-    req.onsuccess = function(event) {
-      let db = event.target.result;
-      let txn = db.transaction([STORE_NAME], "readonly");
-      txn.onabort = makeFailure("Failed to open transaction");
-      let r2 = txn.objectStore(STORE_NAME).get(CONTACT_PROPS.id);
-      r2.onsuccess = function() {
-        db.close();
-        callback(r2.result);
-      };
-      r2.onerror = makeFailure("Failed to get contact");
+  function makeFailure(reason) {
+    return function() {
+      ok(false, reason);
+      SimpleTest.finish();
     };
   };
-}
 
-let savedContact;
+  const { 'utils': Cu } = Components;
+  Cu.import("resource://gre/modules/ContactDB.jsm", window);
+  Cu.importGlobalProperties(["indexedDB"]);
+
+  let cdb = new ContactDB();
+  cdb.init();
 
-let Tests = [
-  saveContact,
+  let CONTACT_PROPS = {
+    id: "ab74671e36be41b680f8f030e7e24ea2",
+    properties: {
+      name: ["Magnificentest foo bar the third"],
+      givenName: ["foo"],
+      familyName: ["bar"],
+      honorificPrefix: ["magnificentest"],
+      honorificSuffix: ["the third"],
+      additionalName: ["addl"],
+      nickname: ["foo"],
+      tel: [
+        {type: ["mobile"], value: "+12345678901", carrier: "ACME Telecommunications", pref: true},
+        {type: ["home", "custom"], value: "7932012346", pref: false},
+      ],
+      email: [{type: ["work"], value: "a@b.c"}, {value: "b@c.d", pref: true}],
+      adr: [
+        {
+          type: ["home"],
+          streetAddress: "street 1",
+          locality: "locality 1",
+          region: "region 1",
+          postalCode: "postal code 1",
+          countryName: "country 1",
+        }
+      ],
+      impp: [{type: ["aim"], value:"im1", pref: true}, {value: "im2"}],
+      org: ["org1", "org2"],
+      jobTitle: ["boss", "superboss"],
+      bday: new Date("1980, 12, 01"),
+      note: ["bla bla bla"],
+      category: ["cat1", "cat2"],
+      url: [{type: ["work", "work2"], value: "www.1.com", pref: true}, {value: "www2.com"}],
+      anniversary: new Date("2000, 12, 01"),
+      sex: "male",
+      genderIdentity: "trisexual",
+      key: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAC4jAAAuIwF4pT92AAACrElEQVQozwXBTW8bRRgA4Hfemf1er7/iJI4Tq7VFlEZN1VZIlapy4MQBTkXcuSH+G/APKnGAAyCVCqmtCHETp64db5zdtdf7NbMzw/OQH378HkCZpmmapqYMy8yrNnadS6026HC/Z7k+SCkEBwKEEKaUQtQAmlDqrucH23nH4BRkJVRcwmod5gcn6LehFgCaEIIalFZaEcLCq73w355RdvY7nfGQGVTlmRXfqMlrUaSUMUQkhCISJIggKj3/YBHt7PRbpy+cwbF7dN/0vEqTMoo3s0tmGAAAoJAgImMq3xZ5WTPbHj4Mho8Nf+QcPtZBLxEkqeQ2WmklkRCtNdNaI1KpVCnqOC3j5ZK++4vnm6xSWZpzwQtRV2mOiBoRpEKtNQAQggjQcCwqinRxJeKlWW93dlqEsa2QRZbF85nWBAAZY4YUgl9fRJWKVuWgmhwHhpD1+ZrfVjAN867rMCne//rq7OuXjWaLCVHnOWHgFDwMw+Tvi09PdhtJXoVC7bWDIi8Lg8qyMk3rYjLzvJh2O30hwK6TpiG7zWDcck9GR17D9wxDcH7/oNtElRa1aZuLDJN4S7/87tssLVg0/eZs/3h0D5R89vR0v+1AVT0YHX31ZDy9uv7IeJrryeyu2+nS50/PqOXM5qt8Nf/jv08UwTfN27vkchldLpPf/nx/nqSz5sbzhkTYzLRppzNYre/ycrMIZwqsHdf96fd/Xr354AYBr/jESWhgGb6zVSuGrrQS1j4Zk8nc2Hs7frFb3Phc6+fOKDGLKOJTHvlj2u85N4t6vbw7OM4YRVquboPdsPNZ9eb8pvfAOf2iN4dN3EzWadnoO5JY19Oo0TYtw1t8TBqBR9v7wbOXROLWtZ3PH937+ZfXrb6BUHEbXL+FCIfDw92e5zebg8GR54r/AaMVcBxE6hgPAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDEyLTA3LTIxVDEwOjUzOjE5LTA0OjAwYyXbYgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMi0wNy0yMVQxMDo1MzoxOS0wNDowMBJ4Y94AAAARdEVYdGpwZWc6Y29sb3JzcGFjZQAyLHVVnwAAACB0RVh0anBlZzpzYW1wbGluZy1mYWN0b3IAMXgxLDF4MSwxeDHplfxwAAAAAElFTkSuQmCC"
+    }
+  };
 
-  getContact(function(contact) {
-    savedContact = contact;
-    next();
-  }),
+  function deleteDatabase(then) {
+    cdb.close();
+    let req = indexedDB.deleteDatabase(DB_NAME);
+    req.onsuccess = then;
+    req.onblocked = makeFailure("blocked");
+    req.onupgradeneeded = makeFailure("onupgradeneeded");
+    req.onerror = makeFailure("onerror");
+  }
 
-  function() {
-    deleteDatabase(function() {
-      info("slow upgrade");
-      cdb.useFastUpgrade = false;
-      cdb.init();
+  function saveContact() {
+    // takes fast upgrade path
+    cdb.saveContact(CONTACT_PROPS,
+      function() {
+        ok(true, "Saved contact successfully");
+        next();
+      }
+    );
+  }
+
+  function getContact(callback) {
+    return function() {
+      let req = indexedDB.open(STORE_NAME, DB_VERSION);
+      req.onsuccess = function(event) {
+        let db = event.target.result;
+        let txn = db.transaction([STORE_NAME], "readonly");
+        txn.onabort = makeFailure("Failed to open transaction");
+        let r2 = txn.objectStore(STORE_NAME).get(CONTACT_PROPS.id);
+        r2.onsuccess = function() {
+          db.close();
+          callback(r2.result);
+        };
+        r2.onerror = makeFailure("Failed to get contact");
+      };
+    };
+  }
+
+  let savedContact;
+
+  let Tests = [
+    saveContact,
+
+    getContact(function(contact) {
+      savedContact = contact;
       next();
-    });
-  },
+    }),
+
+    function() {
+      deleteDatabase(function() {
+        info("slow upgrade");
+        cdb.useFastUpgrade = false;
+        cdb.init();
+        next();
+      });
+    },
+
+    saveContact,
 
-  saveContact,
+    getContact(function(contact) {
+      checkDBContacts(savedContact, contact);
+      next();
+    }),
+  ];
 
-  getContact(function(contact) {
-    checkDBContacts(savedContact, contact);
+  function next() {
+    let step = Tests.shift();
+    if (step) {
+      step();
+    } else {
+      info("All done");
+      SimpleTest.finish();
+    }
+  }
+
+  // Skip tests on Android
+  if (!isAndroid) {
+    SimpleTest.waitForExplicitFinish();
     next();
-  }),
-];
-
-function next() {
-  let step = Tests.shift();
-  if (step) {
-    step();
   } else {
-    info("All done");
-    SimpleTest.finish();
+    ok(true, "Skip test on Android");
   }
-}
 
-// Skip tests on Android
-if (!isAndroid) {
-  SimpleTest.waitForExplicitFinish();
-  next();
-} else {
-  ok(true, "Skip test on Android");
-}
+  ]]>
+  </script>
 
-</script>
-</pre>
-</body>
-</html>
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=889239"
+     target="_blank">Mozilla Bug 889239</a>
+  </body>
+</window>
--- a/dom/datastore/DataStore.jsm
+++ b/dom/datastore/DataStore.jsm
@@ -23,16 +23,17 @@ const REVISION_VOID = "void";
 // and yet we don't know if it's too low or too high.
 const MAX_REQUESTS = 25;
 
 Cu.import("resource://gre/modules/DataStoreCursor.jsm");
 Cu.import("resource://gre/modules/DataStoreDB.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.importGlobalProperties(["indexedDB"]);
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsIMessageSender");
 
 /* Helper functions */
 function createDOMError(aWindow, aEvent) {
   return new aWindow.DOMError(aEvent.target.error.name);
--- a/dom/datastore/DataStoreDB.jsm
+++ b/dom/datastore/DataStoreDB.jsm
@@ -14,16 +14,17 @@ function debug(s) {
 
 const DATASTOREDB_VERSION = 1;
 const DATASTOREDB_OBJECTSTORE_NAME = 'DataStoreDB';
 const DATASTOREDB_REVISION = 'revision';
 const DATASTOREDB_REVISION_INDEX = 'revisionIndex';
 
 Cu.import('resource://gre/modules/IndexedDBHelper.jsm');
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.importGlobalProperties(["indexedDB"]);
 
 XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
                                    "@mozilla.org/uuid-generator;1",
                                    "nsIUUIDGenerator");
 
 this.DataStoreDB = function DataStoreDB() {}
 
 DataStoreDB.prototype = {
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -420,17 +420,18 @@ IndexedDatabaseManager::DefineIndexedDB(
       !IDBFactoryBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBFileHandleBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBIndexBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBKeyRangeBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBObjectStoreBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBOpenDBRequestBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBRequestBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBTransactionBinding::GetConstructorObject(aCx, aGlobal) ||
-      !IDBVersionChangeEventBinding::GetConstructorObject(aCx, aGlobal)) {
+      !IDBVersionChangeEventBinding::GetConstructorObject(aCx, aGlobal))
+  {
     return false;
   }
 
   nsRefPtr<IDBFactory> factory;
   if (NS_FAILED(IDBFactory::Create(aCx, aGlobal, nullptr,
                                    getter_AddRefs(factory)))) {
     return false;
   }
--- a/dom/indexedDB/test/unit/xpcshell.ini
+++ b/dom/indexedDB/test/unit/xpcshell.ini
@@ -25,17 +25,17 @@ support-files =
 [test_cursor_update_updates_indexes.js]
 [test_cursors.js]
 [test_deleteDatabase.js]
 [test_deleteDatabase_interactions.js]
 [test_event_source.js]
 [test_getAll.js]
 [test_globalObjects_ipc.js]
 # FIXME/bug 575918: out-of-process xpcshell is broken on OS X
-#skip-if = os == "mac" || os == "android"
+skip-if = os == "mac" || os == "android"
 [test_globalObjects_other.js]
 [test_globalObjects_xpc.js]
 [test_global_data.js]
 [test_index_empty_keyPath.js]
 [test_index_getAll.js]
 [test_index_getAllObjects.js]
 [test_index_object_cursors.js]
 [test_index_update_delete.js]