(function injectPageContextHooks() { const injectionCode = ` (function() { console.log("[PAGE-INJECT] Installing hooks in page context"); const propertyHooks = { isPaidUser: true, isLoggedIn: true, userHasSubscription: true, userEmail: "hi@httptoolkit.com", mightBePaidUser: true, isPastDueUser: false, userSubscription: { status: "active", plan: "pro", sku: "sku", tierCode: "pro", interval: "monthly", quantity: 1, expiry: new Date("2999-01-01"), updateBillingDetailsUrl: "https://httptoolkit.com/", cancelSubscriptionUrl: "https://httptoolkit.com/", lastReceiptUrl: "https://httptoolkit.com/", canManageSubscription: true } }; const hookedObjects = new WeakSet(); // Override Object.defineProperty to intercept all property definitions const originalDefineProperty = Object.defineProperty; Object.defineProperty = function(target, prop, descriptor) { // Intercept our target properties if (prop in propertyHooks) { console.log("[PAGE-INJECT] Intercepting defineProperty for: " + prop); if (descriptor && descriptor.get) { const originalGetter = descriptor.get; descriptor.get = function() { const originalValue = originalGetter.call(this); console.log("[PAGE-INJECT] " + prop + " getter called, original=" + originalValue + ", returning=" + JSON.stringify(propertyHooks[prop])); return propertyHooks[prop]; }; } else if (descriptor && descriptor.value !== undefined) { console.log("[PAGE-INJECT] " + prop + " value being defined, overriding to " + JSON.stringify(propertyHooks[prop])); descriptor.value = propertyHooks[prop]; } } return originalDefineProperty.call(this, target, prop, descriptor); }; // Hook Object.defineProperties too const originalDefineProperties = Object.defineProperties; Object.defineProperties = function(target, props) { for (let prop in props) { if (prop in propertyHooks) { console.log("[PAGE-INJECT] Intercepting defineProperties for: " + prop); if (props[prop].get) { const originalGetter = props[prop].get; props[prop].get = function() { const originalValue = originalGetter.call(this); console.log("[PAGE-INJECT] " + prop + " getter called, original=" + originalValue + ", returning=" + JSON.stringify(propertyHooks[prop])); return propertyHooks[prop]; }; } else if (props[prop].value !== undefined) { props[prop].value = propertyHooks[prop]; } } } return originalDefineProperties.call(this, target, props); }; // Periodically scan and patch existing objects function scanAndPatch() { // Search through window and common store locations const searchPaths = [ window, window.accountStore, window.stores && window.stores.accountStore, window.appState && window.appState.accountStore, ]; searchPaths.forEach((obj, idx) => { if (!obj || hookedObjects.has(obj)) return; try { Object.keys(propertyHooks).forEach(prop => { try { const desc = Object.getOwnPropertyDescriptor(obj, prop); if (desc && desc.configurable) { console.log("[PAGE-INJECT] Found " + prop + " on object #" + idx + ", patching..."); if (desc.get) { const originalGetter = desc.get; Object.defineProperty(obj, prop, { get: function() { const originalValue = originalGetter.call(this); console.log("[PAGE-INJECT] " + prop + " getter intercepted, original=" + originalValue + ", returning=" + JSON.stringify(propertyHooks[prop])); return propertyHooks[prop]; }, set: desc.set, configurable: true, enumerable: desc.enumerable }); } else if (desc.writable) { obj[prop] = propertyHooks[prop]; console.log("[PAGE-INJECT] " + prop + " value set to " + JSON.stringify(propertyHooks[prop])); } } } catch (e) { // Ignore individual property errors } }); hookedObjects.add(obj); } catch (e) { // Ignore object access errors } }); // Also try to find accountStore by scanning window properties try { for (let key in window) { try { const obj = window[key]; if (obj && typeof obj === 'object' && 'accountStore' in obj) { console.log("[PAGE-INJECT] Found accountStore in window." + key); const store = obj.accountStore; if (store && !hookedObjects.has(store)) { Object.keys(propertyHooks).forEach(prop => { try { const desc = Object.getOwnPropertyDescriptor(store, prop); if (desc && desc.configurable && desc.get) { const originalGetter = desc.get; Object.defineProperty(store, prop, { get: function() { const originalValue = originalGetter.call(this); console.log("[PAGE-INJECT] accountStore." + prop + " intercepted, original=" + originalValue + ", returning=" + JSON.stringify(propertyHooks[prop])); return propertyHooks[prop]; }, set: desc.set, configurable: true, enumerable: desc.enumerable }); } } catch (e) {} }); hookedObjects.add(store); } } } catch (e) {} } } catch (e) {} } // Run initial scan scanAndPatch(); // Scan periodically for late-initialized stores let scanCount = 0; const scanInterval = setInterval(() => { scanCount++; scanAndPatch(); if (scanCount >= 10) { clearInterval(scanInterval); console.log("[PAGE-INJECT] Stopped periodic scanning after 10 attempts"); } }, 100); console.log("[PAGE-INJECT] Hooks installed successfully"); })(); `; function injectScript() { try { const script = document.createElement('script'); script.textContent = injectionCode; (document.head || document.documentElement).appendChild(script); script.remove(); // Clean up the script tag console.log("[PRELOAD] Injected page context hooks"); } catch (e) { console.error("[PRELOAD] Failed to inject hooks:", e); } } // Try to inject immediately if DOM is ready, otherwise wait if (document.documentElement) { injectScript(); } else { // Wait for document to be created const observer = new MutationObserver(() => { if (document.documentElement) { observer.disconnect(); injectScript(); } }); observer.observe(document, { childList: true, subtree: true }); // Also try on DOMContentLoaded as backup if (document.addEventListener) { document.addEventListener('DOMContentLoaded', injectScript, { once: true }); } } })();