/*
 * Bug 1278037 - A Test case for checking whether forgetting APIs are working for the quota manager.
 */

const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;

const TEST_HOST = "example.com";
const TEST_URL = "http://" + TEST_HOST + "/browser/browser/components/contextualidentity/test/browser/";

const USER_CONTEXTS = [
  "default",
  "personal",
];

//
// Support functions.
//

async function openTabInUserContext(uri, userContextId) {
  // Open the tab in the correct userContextId.
  let tab = BrowserTestUtils.addTab(gBrowser, uri, {userContextId});

  // Select tab and make sure its browser is focused.
  gBrowser.selectedTab = tab;
  tab.ownerGlobal.focus();

  let browser = gBrowser.getBrowserForTab(tab);
  await BrowserTestUtils.browserLoaded(browser);
  return {tab, browser};
}

// Setup an entry for the indexedDB.
async function setupIndexedDB(browser) {
  await ContentTask.spawn(browser, { input: "TestForgetAPIs" }, async function(arg) {
    let request = content.indexedDB.open("idb", 1);

    request.onerror = function() {
      throw new Error("error opening db connection");
    };

    request.onupgradeneeded = event => {
      let db = event.target.result;
      let store = db.createObjectStore("obj", { keyPath: "id" });
      store.createIndex("userContext", "userContext", { unique: false });
    };

    let db = await new Promise(resolve => {
      request.onsuccess = event => {
        resolve(event.target.result);
      };
    });

    // Add an entry into the indexedDB.
    let transaction = db.transaction(["obj"], "readwrite");
    let store = transaction.objectStore("obj");
    store.add({id: 1, userContext: arg.input});

    await new Promise(resolve => {
      transaction.oncomplete = () => {
        resolve();
      };
    });

    // Check the indexedDB has been set properly.
    transaction = db.transaction(["obj"], "readonly");
    store = transaction.objectStore("obj");
    let getRequest = store.get(1);
    await new Promise(resolve => {
      getRequest.onsuccess = () => {
        let res = getRequest.result;
        is(res.userContext, arg.input, "Check the indexedDB value");
        resolve();
      };
    });
  });
}

// Check whether the indexedDB has been cleared.
async function checkIndexedDB(browser) {
  await ContentTask.spawn(browser, null, async function() {
    let request = content.indexedDB.open("idb", 1);

    let db = await new Promise(done => {
      request.onsuccess = event => {
        done(event.target.result);
      };
    });

    try {
      db.transaction(["obj"], "readonly");
      ok(false, "The indexedDB should not exist");
    } catch (e) {
      is(e.name, "NotFoundError", "The indexedDB does not exist as expected");
    }
  });
}

//
// Test functions.
//

add_task(async function setup() {
  // Make sure userContext is enabled.
  await SpecialPowers.pushPrefEnv({"set": [
      [ "privacy.userContext.enabled", true ],
  ]});
});

add_task(async function test_quota_clearStoragesForPrincipal() {
  let tabs = [];

  for (let userContextId of Object.keys(USER_CONTEXTS)) {
    // Open our tab in the given user context.
    tabs[userContextId] = await openTabInUserContext(TEST_URL + "empty_file.html", userContextId);

    // Setup an entry for the indexedDB.
    await setupIndexedDB(tabs[userContextId].browser);

    // Close this tab.
    await BrowserTestUtils.removeTab(tabs[userContextId].tab);
  }

  // Using quota manager to clear all indexed DB for a given domain.
  let qms = Cc["@mozilla.org/dom/quota-manager-service;1"].
              getService(Ci.nsIQuotaManagerService);

  let caUtils = {};
  let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
                       getService(Ci.mozIJSSubScriptLoader);
  scriptLoader.loadSubScript("chrome://global/content/contentAreaUtils.js",
                             caUtils);
  let httpURI = caUtils.makeURI("http://" + TEST_HOST);
  let httpPrincipal = Services.scriptSecurityManager
                              .createCodebasePrincipal(httpURI, {});
  qms.clearStoragesForPrincipal(httpPrincipal, null, true);

  for (let userContextId of Object.keys(USER_CONTEXTS)) {
    // Open our tab in the given user context.
    tabs[userContextId] = await openTabInUserContext(TEST_URL + "empty_file.html", userContextId);

    // Check whether indexed DB has been cleared.
    await checkIndexedDB(tabs[userContextId].browser);

    // Close this tab.
    await BrowserTestUtils.removeTab(tabs[userContextId].tab);
  }
});
