if (!window.chrome) {
  // Use the exact property descriptor found in headful Chrome
  // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`
  Object.defineProperty(window, "chrome", {
    writable: true,
    enumerable: true,
    configurable: false, // note!
    value: {}, // We'll extend that later
  });
}

// Ensures that the chrome object is not undefined in headless mode
window.chrome = {
  runtime: {},
};

// That means we're running headful and don't need to mock anything
if (!("app" in window.chrome)) {

  const makeError = {
    ErrorInInvocation: (fn) => {
      const err = new TypeError(`Error in invocation of app.${fn}()`);
      return utils.stripErrorWithAnchor(err, `at ${fn} (eval at <anonymous>`);
    },
  };
  
  // There's a some static data in that property which doesn't seem to change,
  // we should periodically check for updates: `JSON.stringify(window.app, null, 2)`
  const STATIC_DATA = JSON.parse(
    `
    {
    "isInstalled": false,
    "InstallState": {
    "DISABLED": "disabled",
    "INSTALLED": "installed",
    "NOT_INSTALLED": "not_installed"
    },
    "RunningState": {
    "CANNOT_RUN": "cannot_run",
    "READY_TO_RUN": "ready_to_run",
    "RUNNING": "running"
    }
    }
        `.trim()
  );
  
  window.chrome.app = {
    ...STATIC_DATA,
  
    get isInstalled() {
      return false;
    },
  
    getDetails: function getDetails() {
      if (arguments.length) {
        throw makeError.ErrorInInvocation(`getDetails`);
      }
      return null;
    },
    getIsInstalled: function getDetails() {
      if (arguments.length) {
        throw makeError.ErrorInInvocation(`getIsInstalled`);
      }
      return false;
    },
    runningState: function getDetails() {
      if (arguments.length) {
        throw makeError.ErrorInInvocation(`runningState`);
      }
      return "cannot_run";
    },
  };
  utils.patchToStringNested(window.chrome.app);
}
