"use strict";

XPCOMUtils.defineLazyModuleGetter(this, "ExtensionStorage",
                                  "resource://gre/modules/ExtensionStorage.jsm");
Cu.import("resource://gre/modules/Services.jsm");

function storageApiFactory(context) {
  function sanitize(items) {
    // The schema validator already takes care of arrays (which are only allowed
    // to contain strings). Strings and null are safe values.
    if (typeof items != "object" || items === null || Array.isArray(items)) {
      return items;
    }
    // If we got here, then `items` is an object generated by `ObjectType`'s
    // `normalize` method from Schemas.jsm. The object returned by `normalize`
    // lives in this compartment, while the values live in compartment of
    // `context.contentWindow`. The `sanitize` method runs with the principal
    // of `context`, so we cannot just use `ExtensionStorage.sanitize` because
    // it is not allowed to access properties of `items`.
    // So we enumerate all properties and sanitize each value individually.
    let sanitized = {};
    for (let [key, value] of Object.entries(items)) {
      sanitized[key] = ExtensionStorage.sanitize(value, context);
    }
    return sanitized;
  }
  return {
    storage: {
      local: {
        get: function(keys) {
          keys = sanitize(keys);
          return context.childManager.callParentAsyncFunction("storage.local.get", [
            keys,
          ]);
        },
        set: function(items) {
          items = sanitize(items);
          return context.childManager.callParentAsyncFunction("storage.local.set", [
            items,
          ]);
        },
      },

      sync: {
        get: function(keys) {
          keys = sanitize(keys);
          return context.childManager.callParentAsyncFunction("storage.sync.get", [
            keys,
          ]);
        },
        set: function(items) {
          items = sanitize(items);
          return context.childManager.callParentAsyncFunction("storage.sync.set", [
            items,
          ]);
        },
      },
    },
  };
}
extensions.registerSchemaAPI("storage", "addon_child", storageApiFactory);
extensions.registerSchemaAPI("storage", "content_child", storageApiFactory);
