From a28e3a1deeddf4eb699679c921cb3774e36bd389 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 9 Dec 2021 18:23:47 -0600 Subject: [PATCH 1/3] Switch functions to use synchronous DB reads Motivation: instead of relying on the asynchronous IndexDB reads for the `isPushEnabled` and `isOptedOut` values, we switch to use the synchronous `LocalStorage` getters instead. The reason for this is simple, asynchronous DB reads make use of the message queue which queues asynchronous calls and is outside of the event loop call stack. As soon as the message queue is used, the entire call stack loses its designation as "user-initiated" even though it may have been. We must thus avoid using any executions that would require use of the message queue to ensure the requirement is met. --- src/managers/CustomLinkManager.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/managers/CustomLinkManager.ts b/src/managers/CustomLinkManager.ts index 38236e643..b36a9a655 100644 --- a/src/managers/CustomLinkManager.ts +++ b/src/managers/CustomLinkManager.ts @@ -4,6 +4,7 @@ import { ResourceLoadState } from "../services/DynamicResourceLoader"; import { CUSTOM_LINK_CSS_CLASSES, CUSTOM_LINK_CSS_SELECTORS } from "../slidedown/constants"; import { addCssClass } from "../utils"; import { AppUserConfigCustomLinkOptions } from "../models/Prompts"; +import LocalStorage from "../utils/LocalStorage"; export class CustomLinkManager { private config: AppUserConfigCustomLinkOptions | undefined; @@ -23,7 +24,7 @@ export class CustomLinkManager { Log.info("OneSignal: initializing customlink"); - if (!this.config?.unsubscribeEnabled && await CustomLinkManager.isPushEnabled()) { + if (!this.config?.unsubscribeEnabled && CustomLinkManager.isPushEnabled()) { this.hideCustomLinkContainers(); return; } @@ -57,7 +58,7 @@ export class CustomLinkManager { addCssClass(explanation, this.config.size); } - if (await CustomLinkManager.isPushEnabled()) { + if (CustomLinkManager.isPushEnabled()) { addCssClass(explanation, CUSTOM_LINK_CSS_CLASSES.state.subscribed); } else { addCssClass(explanation, CUSTOM_LINK_CSS_CLASSES.state.unsubscribed); @@ -86,7 +87,7 @@ export class CustomLinkManager { addCssClass(subscribeButton, this.config.style); } - if (await CustomLinkManager.isPushEnabled()) { + if (CustomLinkManager.isPushEnabled()) { addCssClass(subscribeButton, CUSTOM_LINK_CSS_CLASSES.state.subscribed); } else { addCssClass(subscribeButton, CUSTOM_LINK_CSS_CLASSES.state.unsubscribed); @@ -128,23 +129,23 @@ export class CustomLinkManager { } private async handleClick(element: HTMLElement): Promise { - if (await CustomLinkManager.isPushEnabled()) { + if (CustomLinkManager.isPushEnabled()) { await OneSignal.setSubscription(false); await this.setTextFromPushStatus(element); } else { - if (!await CustomLinkManager.isOptedOut()) { + if (!CustomLinkManager.isOptedOut()) { const autoAccept = !OneSignal.environmentInfo.requiresUserInteraction; const options: RegisterOptions = { autoAccept }; await OneSignal.registerForPushNotifications(options); // once subscribed, prevent unsubscribe by hiding customlinks - if (!this.config?.unsubscribeEnabled && await CustomLinkManager.isPushEnabled()) { + if (!this.config?.unsubscribeEnabled && CustomLinkManager.isPushEnabled()) { this.hideCustomLinkContainers(); } return; } await OneSignal.setSubscription(true); // once subscribed, prevent unsubscribe by hiding customlinks - if (!this.config?.unsubscribeEnabled && await CustomLinkManager.isPushEnabled()) { + if (!this.config?.unsubscribeEnabled && CustomLinkManager.isPushEnabled()) { this.hideCustomLinkContainers(); } } @@ -152,13 +153,13 @@ export class CustomLinkManager { private async setTextFromPushStatus(element: HTMLElement): Promise { if (this.config?.text?.subscribe) { - if (!await CustomLinkManager.isPushEnabled()) { + if (!CustomLinkManager.isPushEnabled()) { element.textContent = this.config.text.subscribe; } } if (this.config?.text?.unsubscribe) { - if (await CustomLinkManager.isPushEnabled()) { + if (CustomLinkManager.isPushEnabled()) { element.textContent = this.config.text.unsubscribe; } } @@ -182,11 +183,11 @@ export class CustomLinkManager { return Array.prototype.slice.call(containers); } - static async isPushEnabled(): Promise { - return await OneSignal.privateIsPushNotificationsEnabled(); + static isPushEnabled(): boolean { + return LocalStorage.getIsPushNotificationsEnabled(); } - static async isOptedOut(): Promise { - return await OneSignal.internalIsOptedOut(); + static isOptedOut(): boolean { + return LocalStorage.getIsOptedOut(); } } From 517bf00d9ffe90daa40950c5040cd5111800a2d1 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 9 Dec 2021 18:45:51 -0600 Subject: [PATCH 2/3] Fix tests to return instead of resolve values --- test/unit/prompts/CustomLink.ts | 66 ++++++++++++++++----------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/test/unit/prompts/CustomLink.ts b/test/unit/prompts/CustomLink.ts index 739e3a0bf..b279128ab 100644 --- a/test/unit/prompts/CustomLink.ts +++ b/test/unit/prompts/CustomLink.ts @@ -61,8 +61,8 @@ test('customlink: container: not render if disabled', async t => { }); test('customlink: container: render if enabled, explanation present', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); await new CustomLinkManager(config).initialize(); @@ -76,8 +76,8 @@ test('customlink: container: render if enabled, explanation present', async t => }); test('customlink: container: render if enabled, no explanation', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); config.text.explanation = ""; await new CustomLinkManager(config).initialize(); @@ -92,7 +92,7 @@ test('customlink: container: render if enabled, no explanation', async t => { test("customlink: push enabled text and state", async t => { sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); const manager = new CustomLinkManager(config); await manager.initialize(); @@ -104,8 +104,8 @@ test("customlink: push enabled text and state", async t => { }); test('customlink: push disabled text and state', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(false); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(false); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); await new CustomLinkManager(config).initialize(); @@ -117,8 +117,8 @@ test('customlink: push disabled text and state', async t => { }); test('customlink: subscribe: intitialized, push enabled', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); await new CustomLinkManager(config).initialize(); @@ -131,8 +131,8 @@ test('customlink: subscribe: intitialized, push enabled', async t => { }); test('customlink: subscribe: intitialized, push disabled', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(false); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(false); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); await new CustomLinkManager(config).initialize(); @@ -145,8 +145,8 @@ test('customlink: subscribe: intitialized, push disabled', async t => { }); test('customlink: subscribe: unsubscribe disabled', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); config.unsubscribeEnabled = false; await new CustomLinkManager(config).initialize(); @@ -158,8 +158,8 @@ test('customlink: subscribe: unsubscribe disabled', async t => { }); test('customlink: subscribe: unsubscribe enabled', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); await new CustomLinkManager(config).initialize(); @@ -175,8 +175,8 @@ test('customlink: subscribe: unsubscribe enabled', async t => { }); test('customlink: subscribe: button', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); config.style = "button"; await new CustomLinkManager(config).initialize(); @@ -191,8 +191,8 @@ test('customlink: subscribe: button', async t => { }); test('customlink: subscribe: link', async t => { - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); config.style = "link"; await new CustomLinkManager(config).initialize(); @@ -207,9 +207,9 @@ test('customlink: subscribe: link', async t => { }); test('customlink: reinitialize', async t => { - sandbox.stub(OneSignal, 'privateIsPushNotificationsEnabled').returns(false); - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(false); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(OneSignal, 'privateIsPushNotificationsEnabled').resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(false); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); await new CustomLinkManager(config).initialize(); await new CustomLinkManager(config).initialize(); @@ -220,8 +220,8 @@ test('customlink: reinitialize', async t => { test('customlink: subscribe: clicked: subscribed -> unsubscribed', async t => { const subscriptionPromise = EventsTestHelper.getSubscriptionPromise(); new EventsTestHelper(sandbox).simulateSubscribingAfterNativeAllow(); - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); const subscriptionSpy = sandbox.stub(OneSignal, 'setSubscription').callsFake(async () => { await setSubscriptionStub(); @@ -250,14 +250,14 @@ test('customlink: subscribe: clicked: subscribed -> unsubscribed', async t => { test('customlink: subscribe: clicked: unsubscribed -> subscribed. https. opted out', async t => { const subscriptionPromise = EventsTestHelper.getSubscriptionPromise(); - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(false); sandbox.stub(OneSignalUtils, 'isUsingSubscriptionWorkaround').returns(false); const subscriptionSpy = sandbox.stub(OneSignal, 'setSubscription').callsFake(async () => { await setSubscriptionStub(); }); // TODO: why is this called in custom link sandbox.stub(DismissHelper, 'wasPromptOfTypeDismissed').returns(false); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(true); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(true); sandbox.stub(OneSignal.context.subscriptionManager, 'getSubscriptionState').returns({ subscribed: true, optedOut: true, @@ -282,12 +282,12 @@ test('customlink: subscribe: clicked: unsubscribed -> subscribed. https. opted o test('customlink: subscribe: clicked: unsubscribed -> subscribed. https. never subscribed.', async t => { TestEnvironment.overrideEnvironmentInfo({ requiresUserInteraction: false }); const subscriptionPromise = EventsTestHelper.getSubscriptionPromise(); - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(false); const subscriptionSpy = sandbox.stub(OneSignal, 'registerForPushNotifications').callsFake(async () => { await setSubscriptionStub(); }); sandbox.stub(OneSignalUtils, 'isUsingSubscriptionWorkaround').returns(false); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); sandbox.stub(OneSignal.context.subscriptionManager, 'getSubscriptionState').returns({ subscribed: false, @@ -310,12 +310,12 @@ test('customlink: subscribe: clicked: unsubscribed -> subscribed. https. never s test('customlink: subscribe: clicked: unsubscribed -> subscribed. http. never subscribed.', async t => { const subscriptionPromise = EventsTestHelper.getSubscriptionPromise(); TestEnvironment.overrideEnvironmentInfo({ requiresUserInteraction: false }); - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(false); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(false); const registerSpy = sandbox.stub(OneSignal, 'registerForPushNotifications').callsFake(async () => { await setSubscriptionStub(); }); sandbox.stub(OneSignalUtils, 'isUsingSubscriptionWorkaround').returns(true); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(false); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(false); await new CustomLinkManager(config).initialize(); @@ -337,10 +337,10 @@ test('customlink: subscribe: clicked: unsubscribed -> subscribed. http. never su test('customlink: subscribe: clicked: unsubscribed -> subscribed. http. opted out.', async t => { const subscriptionPromise = EventsTestHelper.getSubscriptionPromise(); - sandbox.stub(PermissionManager.prototype, 'getReportedNotificationPermission').resolves(false); + sandbox.stub(PermissionManager.prototype, 'getReportedNotificationPermission').returns(false); sandbox.stub(OneSignalUtils, 'isUsingSubscriptionWorkaround').returns(true); - sandbox.stub(CustomLinkManager, "isPushEnabled").resolves(false); - sandbox.stub(CustomLinkManager, "isOptedOut").resolves(true); + sandbox.stub(CustomLinkManager, "isPushEnabled").returns(false); + sandbox.stub(CustomLinkManager, "isOptedOut").returns(true); const subscriptionSpy = sandbox.stub(OneSignal, 'setSubscription').callsFake(async () => { await setSubscriptionStub(); }); From 4671d5a256f74d17afbd4c83e972c8bb017204f9 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 9 Dec 2021 18:25:04 -0600 Subject: [PATCH 3/3] 151511 Release Commit Motivation: Update `sdkVersion` in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4890036f4..4de00b3f9 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "build:dev-stag": "./build/scripts/build.sh -f development -t staging" }, "config": { - "sdkVersion": "151510" + "sdkVersion": "151511" }, "repository": { "type": "git",