chrome-shim.ts

4.4 KB · raw

1// Capacitor chrome shim. The mobile foreground imports background modules that2// were written for MV3, so this supplies the small chrome.* surface they touch.34import { Preferences } from "@capacitor/preferences";56declare const __APP_VERSION__: string;78type Listener<T extends (...args: any[]) => void> = {9  addListener: (_listener: T) => void;10  removeListener: (_listener: T) => void;11};1213const sessionStore = new Map<string, unknown>();1415function noopListener<T extends (...args: any[]) => void>(): Listener<T> {16  return {17    addListener: () => {},18    removeListener: () => {},19  };20}2122async function keysFor(input: string | string[] | Record<string, unknown> | null): Promise<string[]> {23  if (input === null) {24    const result = await Preferences.keys();25    return result.keys;26  }27  if (Array.isArray(input)) return input;28  if (typeof input === "string") return [input];29  return Object.keys(input);30}3132async function localGet(keys: string | string[] | Record<string, unknown> | null): Promise<Record<string, unknown>> {33  const result: Record<string, unknown> = {};34  for (const key of await keysFor(keys)) {35    const { value } = await Preferences.get({ key });36    if (value === null) continue;37    try {38      result[key] = JSON.parse(value);39    } catch {40      result[key] = value;41    }42  }43  return result;44}4546async function localSet(items: Record<string, unknown>): Promise<void> {47  for (const [key, value] of Object.entries(items)) {48    await Preferences.set({ key, value: JSON.stringify(value) });49  }50}5152async function localRemove(keys: string | string[]): Promise<void> {53  const keyArray = Array.isArray(keys) ? keys : [keys];54  for (const key of keyArray) {55    await Preferences.remove({ key });56  }57}5859function sessionKeys(input: string | string[] | Record<string, unknown> | null): string[] {60  if (input === null) return [...sessionStore.keys()];61  if (Array.isArray(input)) return input;62  if (typeof input === "string") return [input];63  return Object.keys(input);64}6566const chromeShim = {67  runtime: {68    id: "peach-mobile",69    getManifest: () => ({70      name: "Peach",71      version: typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : "0.0.0",72      manifest_version: 3,73    }),74    sendMessage: (_msg: unknown, cb?: (response: unknown) => void) => {75      const response = { ok: false, error: "NO_SERVICE_WORKER" };76      cb?.(response);77      return Promise.resolve(response);78    },79    onMessage: noopListener<(message: unknown) => void>(),80    connect: () => ({81      disconnect: () => {},82      onMessage: noopListener<(message: unknown) => void>(),83      onDisconnect: noopListener<() => void>(),84      postMessage: () => {},85    }),86    lastError: null,87  },88  storage: {89    local: {90      get: localGet,91      set: localSet,92      remove: localRemove,93      clear: () => Preferences.clear(),94    },95    session: {96      get: async (keys: string | string[] | Record<string, unknown> | null) => {97        const result: Record<string, unknown> = {};98        for (const key of sessionKeys(keys)) {99          if (sessionStore.has(key)) result[key] = sessionStore.get(key);100        }101        return result;102      },103      set: async (items: Record<string, unknown>) => {104        for (const [key, value] of Object.entries(items)) {105          sessionStore.set(key, value);106        }107      },108      remove: async (keys: string | string[]) => {109        const keyArray = Array.isArray(keys) ? keys : [keys];110        for (const key of keyArray) sessionStore.delete(key);111      },112      clear: async () => {113        sessionStore.clear();114      },115    },116    onChanged: noopListener<(changes: Record<string, unknown>, areaName: string) => void>(),117  },118  alarms: {119    clear: () => {},120    create: () => {},121    onAlarm: noopListener<(alarm: { name: string }) => void>(),122  },123  idle: {124    setDetectionInterval: () => {},125    onStateChanged: noopListener<(state: string) => void>(),126  },127  tabs: {128    query: (_query: unknown, cb?: (tabs: any[]) => void) => {129      cb?.([]);130      return Promise.resolve([]);131    },132    sendMessage: () => Promise.resolve(undefined),133    create: () => Promise.resolve(undefined),134    onActivated: noopListener<() => void>(),135    onUpdated: noopListener<() => void>(),136  },137  action: {138    openPopup: () => Promise.resolve(),139    setBadgeText: () => Promise.resolve(),140    setBadgeBackgroundColor: () => Promise.resolve(),141  },142  scripting: {143    executeScript: () => Promise.resolve(),144  },145};146147(window as any).chrome = chromeShim;