diff --git a/dist/autofill-debug.js b/dist/autofill-debug.js index 5ff88f0a3..5875c2c2a 100644 --- a/dist/autofill-debug.js +++ b/dist/autofill-debug.js @@ -7110,8 +7110,11 @@ var _InterfacePrototype = _interopRequireDefault(require("./InterfacePrototype.j var _autofillUtils = require("../autofill-utils.js"); var _NativeUIController = require("../UI/controllers/NativeUIController.js"); var _appleUtils = require("@duckduckgo/content-scope-scripts/src/apple-utils"); +var _InContextSignup = require("../InContextSignup.js"); +var _deviceApiCalls = require("../deviceApiCalls/__generated__/deviceApiCalls.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class AndroidInterface extends _InterfacePrototype.default { + inContextSignup = new _InContextSignup.InContextSignup(this); async isEnabled() { return (0, _autofillUtils.autofillEnabled)(this.globalConfig, _appleUtils.processConfig); } @@ -7122,7 +7125,20 @@ class AndroidInterface extends _InterfacePrototype.default { async getAlias() { const { alias - } = await (0, _autofillUtils.sendAndWaitForAnswer)(() => { + } = await (0, _autofillUtils.sendAndWaitForAnswer)(async () => { + if (this.inContextSignup.isAvailable()) { + const { + isSignedIn + } = await this.deviceApi.request(new _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall(null)); + // On Android we can't get the input type data again without + // refreshing the page, so instead we can mutate it now that we + // know the user has Email Protection available. + if (this.globalConfig.availableInputTypes) { + this.globalConfig.availableInputTypes.email = isSignedIn; + } + this.updateForStateChange(); + this.onFinishedAutofill(); + } return window.EmailInterface.showTooltip(); }, 'getAliasResponse'); return alias; @@ -7153,7 +7169,9 @@ class AndroidInterface extends _InterfacePrototype.default { // ...on other domains we assume true because the script wouldn't exist otherwise return true; } - async setupAutofill() {} + async setupAutofill() { + await this.inContextSignup.init(); + } /** * Used by the email web app @@ -7210,6 +7228,14 @@ class AndroidInterface extends _InterfacePrototype.default { } } } + + /** + * Used by the email web app + * Provides functionality to close the window after in-context sign-up or sign-in + */ + closeEmailProtection() { + this.deviceApi.request(new _deviceApiCalls.CloseEmailProtectionTabCall(null)); + } addLogoutListener(handler) { // Only deal with logging out if we're in the email web app if (!this.globalConfig.isDDGDomain) return; @@ -7225,7 +7251,7 @@ class AndroidInterface extends _InterfacePrototype.default { } exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],24:[function(require,module,exports){ +},{"../InContextSignup.js":44,"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9240,7 +9266,7 @@ function initFormSubmissionsApi(forms, matching) { const focusedForm = [...forms.values()].find(form => form.hasFocus(e)); focusedForm?.submitHandler('global keydown + Enter'); } - }); + }, true); /** * Global pointer down events @@ -16543,7 +16569,7 @@ const constants = exports.constants = { Object.defineProperty(exports, "__esModule", { value: true }); -exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; +exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.ShowInContextEmailProtectionSignupPromptCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; var _validatorsZod = require("./validators.zod.js"); var _deviceApi = require("../../../packages/device-api"); /* DO NOT EDIT, this file was generated by scripts/api-call-generator.js */ @@ -16772,7 +16798,16 @@ exports.StartEmailProtectionSignupCall = StartEmailProtectionSignupCall; class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { method = "closeEmailProtectionTab"; } +/** + * @extends {DeviceApiCall} + */ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; +class ShowInContextEmailProtectionSignupPromptCall extends _deviceApi.DeviceApiCall { + method = "ShowInContextEmailProtectionSignupPrompt"; + id = "ShowInContextEmailProtectionSignupPromptResponse"; + resultValidator = _validatorsZod.showInContextEmailProtectionSignupPromptSchema; +} +exports.ShowInContextEmailProtectionSignupPromptCall = ShowInContextEmailProtectionSignupPromptCall; },{"../../../packages/device-api":12,"./validators.zod.js":66}],66:[function(require,module,exports){ "use strict"; @@ -16780,7 +16815,7 @@ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; Object.defineProperty(exports, "__esModule", { value: true }); -exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; +exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.showInContextEmailProtectionSignupPromptSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; var _zod = require("zod"); /* DO NOT EDIT, this file was generated by scripts/api-call-generator.js */ // Generated by ts-to-zod @@ -16843,6 +16878,11 @@ const emailProtectionStoreUserDataParamsSchema = exports.emailProtectionStoreUse userName: _zod.z.string(), cohort: _zod.z.string() }); +const showInContextEmailProtectionSignupPromptSchema = exports.showInContextEmailProtectionSignupPromptSchema = _zod.z.object({ + success: _zod.z.object({ + isSignedIn: _zod.z.boolean() + }) +}); const generatedPasswordSchema = exports.generatedPasswordSchema = _zod.z.object({ value: _zod.z.string(), username: _zod.z.string() @@ -17163,7 +17203,11 @@ const apiSchema = exports.apiSchema = _zod.z.object({ resultValidator: emailProtectionRefreshPrivateAddressResultSchema.optional() })).optional(), startEmailProtectionSignup: _zod.z.record(_zod.z.unknown()).optional(), - closeEmailProtectionTab: _zod.z.record(_zod.z.unknown()).optional() + closeEmailProtectionTab: _zod.z.record(_zod.z.unknown()).optional(), + ShowInContextEmailProtectionSignupPrompt: _zod.z.record(_zod.z.unknown()).and(_zod.z.object({ + id: _zod.z.literal("ShowInContextEmailProtectionSignupPromptResponse").optional(), + resultValidator: showInContextEmailProtectionSignupPromptSchema.optional() + })).optional() }); },{"zod":9}],67:[function(require,module,exports){ @@ -17229,6 +17273,23 @@ class AndroidTransport extends _index.DeviceApiTransport { if (deviceApiCall instanceof _deviceApiCalls.GetAvailableInputTypesCall) { return androidSpecificAvailableInputTypes(this.config); } + if (deviceApiCall instanceof _deviceApiCalls.GetIncontextSignupDismissedAtCall) { + window.BrowserAutofill.getIncontextSignupDismissedAt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } + if (deviceApiCall instanceof _deviceApiCalls.SetIncontextSignupPermanentlyDismissedAtCall) { + return window.BrowserAutofill.setIncontextSignupPermanentlyDismissedAt(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.StartEmailProtectionSignupCall) { + return window.BrowserAutofill.startEmailProtectionSignup(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.CloseEmailProtectionTabCall) { + return window.BrowserAutofill.closeEmailProtectionTab(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall) { + window.BrowserAutofill.showInContextEmailProtectionSignupPrompt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } if (deviceApiCall instanceof _deviceApiCalls.GetAutofillDataCall) { window.BrowserAutofill.getAutofillData(JSON.stringify(deviceApiCall.params)); return waitForResponse(deviceApiCall.id, this.config); diff --git a/dist/autofill.js b/dist/autofill.js index e9bd2867c..f8f022768 100644 --- a/dist/autofill.js +++ b/dist/autofill.js @@ -3165,8 +3165,11 @@ var _InterfacePrototype = _interopRequireDefault(require("./InterfacePrototype.j var _autofillUtils = require("../autofill-utils.js"); var _NativeUIController = require("../UI/controllers/NativeUIController.js"); var _appleUtils = require("@duckduckgo/content-scope-scripts/src/apple-utils"); +var _InContextSignup = require("../InContextSignup.js"); +var _deviceApiCalls = require("../deviceApiCalls/__generated__/deviceApiCalls.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class AndroidInterface extends _InterfacePrototype.default { + inContextSignup = new _InContextSignup.InContextSignup(this); async isEnabled() { return (0, _autofillUtils.autofillEnabled)(this.globalConfig, _appleUtils.processConfig); } @@ -3177,7 +3180,20 @@ class AndroidInterface extends _InterfacePrototype.default { async getAlias() { const { alias - } = await (0, _autofillUtils.sendAndWaitForAnswer)(() => { + } = await (0, _autofillUtils.sendAndWaitForAnswer)(async () => { + if (this.inContextSignup.isAvailable()) { + const { + isSignedIn + } = await this.deviceApi.request(new _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall(null)); + // On Android we can't get the input type data again without + // refreshing the page, so instead we can mutate it now that we + // know the user has Email Protection available. + if (this.globalConfig.availableInputTypes) { + this.globalConfig.availableInputTypes.email = isSignedIn; + } + this.updateForStateChange(); + this.onFinishedAutofill(); + } return window.EmailInterface.showTooltip(); }, 'getAliasResponse'); return alias; @@ -3208,7 +3224,9 @@ class AndroidInterface extends _InterfacePrototype.default { // ...on other domains we assume true because the script wouldn't exist otherwise return true; } - async setupAutofill() {} + async setupAutofill() { + await this.inContextSignup.init(); + } /** * Used by the email web app @@ -3265,6 +3283,14 @@ class AndroidInterface extends _InterfacePrototype.default { } } } + + /** + * Used by the email web app + * Provides functionality to close the window after in-context sign-up or sign-in + */ + closeEmailProtection() { + this.deviceApi.request(new _deviceApiCalls.CloseEmailProtectionTabCall(null)); + } addLogoutListener(handler) { // Only deal with logging out if we're in the email web app if (!this.globalConfig.isDDGDomain) return; @@ -3280,7 +3306,7 @@ class AndroidInterface extends _InterfacePrototype.default { } exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],14:[function(require,module,exports){ +},{"../InContextSignup.js":34,"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],14:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5295,7 +5321,7 @@ function initFormSubmissionsApi(forms, matching) { const focusedForm = [...forms.values()].find(form => form.hasFocus(e)); focusedForm?.submitHandler('global keydown + Enter'); } - }); + }, true); /** * Global pointer down events @@ -12598,7 +12624,7 @@ const constants = exports.constants = { Object.defineProperty(exports, "__esModule", { value: true }); -exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; +exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.ShowInContextEmailProtectionSignupPromptCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; var _validatorsZod = require("./validators.zod.js"); var _deviceApi = require("../../../packages/device-api"); /* DO NOT EDIT, this file was generated by scripts/api-call-generator.js */ @@ -12827,7 +12853,16 @@ exports.StartEmailProtectionSignupCall = StartEmailProtectionSignupCall; class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { method = "closeEmailProtectionTab"; } +/** + * @extends {DeviceApiCall} + */ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; +class ShowInContextEmailProtectionSignupPromptCall extends _deviceApi.DeviceApiCall { + method = "ShowInContextEmailProtectionSignupPrompt"; + id = "ShowInContextEmailProtectionSignupPromptResponse"; + resultValidator = _validatorsZod.showInContextEmailProtectionSignupPromptSchema; +} +exports.ShowInContextEmailProtectionSignupPromptCall = ShowInContextEmailProtectionSignupPromptCall; },{"../../../packages/device-api":2,"./validators.zod.js":56}],56:[function(require,module,exports){ "use strict"; @@ -12835,7 +12870,7 @@ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; Object.defineProperty(exports, "__esModule", { value: true }); -exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; +exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.showInContextEmailProtectionSignupPromptSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; const sendJSPixelParamsSchema = exports.sendJSPixelParamsSchema = null; const addDebugFlagParamsSchema = exports.addDebugFlagParamsSchema = null; const getAutofillCredentialsParamsSchema = exports.getAutofillCredentialsParamsSchema = null; @@ -12846,6 +12881,7 @@ const getIncontextSignupDismissedAtSchema = exports.getIncontextSignupDismissedA const getAliasParamsSchema = exports.getAliasParamsSchema = null; const getAliasResultSchema = exports.getAliasResultSchema = null; const emailProtectionStoreUserDataParamsSchema = exports.emailProtectionStoreUserDataParamsSchema = null; +const showInContextEmailProtectionSignupPromptSchema = exports.showInContextEmailProtectionSignupPromptSchema = null; const generatedPasswordSchema = exports.generatedPasswordSchema = null; const triggerContextSchema = exports.triggerContextSchema = null; const credentialsSchema = exports.credentialsSchema = null; @@ -12938,6 +12974,23 @@ class AndroidTransport extends _index.DeviceApiTransport { if (deviceApiCall instanceof _deviceApiCalls.GetAvailableInputTypesCall) { return androidSpecificAvailableInputTypes(this.config); } + if (deviceApiCall instanceof _deviceApiCalls.GetIncontextSignupDismissedAtCall) { + window.BrowserAutofill.getIncontextSignupDismissedAt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } + if (deviceApiCall instanceof _deviceApiCalls.SetIncontextSignupPermanentlyDismissedAtCall) { + return window.BrowserAutofill.setIncontextSignupPermanentlyDismissedAt(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.StartEmailProtectionSignupCall) { + return window.BrowserAutofill.startEmailProtectionSignup(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.CloseEmailProtectionTabCall) { + return window.BrowserAutofill.closeEmailProtectionTab(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall) { + window.BrowserAutofill.showInContextEmailProtectionSignupPrompt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } if (deviceApiCall instanceof _deviceApiCalls.GetAutofillDataCall) { window.BrowserAutofill.getAutofillData(JSON.stringify(deviceApiCall.params)); return waitForResponse(deviceApiCall.id, this.config); diff --git a/integration-test/helpers/mocks.android.js b/integration-test/helpers/mocks.android.js index 4248c9084..6490b9ec4 100644 --- a/integration-test/helpers/mocks.android.js +++ b/integration-test/helpers/mocks.android.js @@ -44,6 +44,7 @@ export function androidStringReplacements (overrides = {}) { inputType_identities: false, inputType_creditCards: false, emailProtection: true, + emailProtection_incontext_signup: true, password_generation: false, credentials_saving: true, inlineIcon_credentials: true, @@ -75,6 +76,8 @@ export function createAndroidMocks () { const mocks = { /** @type {GetAutofillDataResponse['success']|null} */ getAutofillData: null, + showInContextEmailProtectionSignupPrompt: { isSignedIn: true }, + incontextSignupDismissedAt: {}, /** @type {string|null} */ address: null, isSignedIn: '' @@ -199,6 +202,29 @@ export function createAndroidMocks () { /** @type {MockCall} */ const call = ['storeFormData', request, mocks.getAutofillData] window.__playwright_autofill.mocks.calls.push(JSON.parse(JSON.stringify(call))) + }, + showInContextEmailProtectionSignupPrompt (request) { + return respond('ShowInContextEmailProtectionSignupPrompt', request, mocks.showInContextEmailProtectionSignupPrompt) + }, + getIncontextSignupDismissedAt (request) { + const call = ['getIncontextSignupDismissedAt', request, mocks.incontextSignupDismissedAt] + window.__playwright_autofill.mocks.calls.push(JSON.parse(JSON.stringify(call))) + window.postMessage(JSON.stringify({ + type: 'getIncontextSignupDismissedAt', + success: mocks.incontextSignupDismissedAt + }), window.origin) + }, + setIncontextSignupPermanentlyDismissedAt (request) { + const call = ['setIncontextSignupPermanentlyDismissedAt', request] + window.__playwright_autofill.mocks.calls.push(JSON.parse(JSON.stringify(call))) + }, + startEmailProtectionSignup (request) { + const call = ['startEmailProtectionSignup', request] + window.__playwright_autofill.mocks.calls.push(JSON.parse(JSON.stringify(call))) + }, + closeEmailProtectionTab (request) { + const call = ['closeEmailProtectionTab', request] + window.__playwright_autofill.mocks.calls.push(JSON.parse(JSON.stringify(call))) } } }, mocks) diff --git a/integration-test/tests/incontext-signup.android.spec.js b/integration-test/tests/incontext-signup.android.spec.js new file mode 100644 index 000000000..58f787df6 --- /dev/null +++ b/integration-test/tests/incontext-signup.android.spec.js @@ -0,0 +1,44 @@ +import {createAutofillScript, forwardConsoleMessages, mockedCalls, setupMockedDomain} from '../helpers/harness.js' +import {expect, test as base} from '@playwright/test' +import {emailAutofillPage} from '../helpers/pages.js' +import {androidStringReplacements, createAndroidMocks} from '../helpers/mocks.android.js' +import {testContext} from '../helpers/test-context.js' + +/** + * Tests for email in-context signup events in Android. + */ +const test = testContext(base) + +test.describe('android', () => { + test('should allow user to sign up for Email Protection', async ({page}) => { + await forwardConsoleMessages(page) + await setupMockedDomain(page, 'https://example.com') + + const emailPage = emailAutofillPage(page) + await emailPage.navigate('https://example.com') + + await createAndroidMocks() + .applyTo(page) + + // create + inject the script + await createAutofillScript() + .replaceAll(androidStringReplacements({ + availableInputTypes: { + email: false + } + })) + .platform('android') + .applyTo(page) + + // Checks if in-context signup has already been dismissed + const checkCall = await mockedCalls(page, {names: ['getIncontextSignupDismissedAt']}) + expect(checkCall.length).toBe(1) + + await emailPage.assertDaxIconIsShowing() + await emailPage.clickDirectlyOnDax() + + // Informs native app that it should show the signup prompt + const startCall = await mockedCalls(page, {names: ['ShowInContextEmailProtectionSignupPrompt']}) + expect(startCall.length).toBe(1) + }) +}) diff --git a/src/DeviceInterface/AndroidInterface.js b/src/DeviceInterface/AndroidInterface.js index 658f1f6aa..b44fed18d 100644 --- a/src/DeviceInterface/AndroidInterface.js +++ b/src/DeviceInterface/AndroidInterface.js @@ -2,8 +2,12 @@ import InterfacePrototype from './InterfacePrototype.js' import {autofillEnabled, sendAndWaitForAnswer} from '../autofill-utils.js' import { NativeUIController } from '../UI/controllers/NativeUIController.js' import {processConfig} from '@duckduckgo/content-scope-scripts/src/apple-utils' +import { InContextSignup } from '../InContextSignup.js' +import { CloseEmailProtectionTabCall, ShowInContextEmailProtectionSignupPromptCall } from '../deviceApiCalls/__generated__/deviceApiCalls.js' class AndroidInterface extends InterfacePrototype { + inContextSignup = new InContextSignup(this) + async isEnabled () { return autofillEnabled(this.globalConfig, processConfig) } @@ -12,7 +16,18 @@ class AndroidInterface extends InterfacePrototype { * @returns {Promise} */ async getAlias () { - const { alias } = await sendAndWaitForAnswer(() => { + const { alias } = await sendAndWaitForAnswer(async () => { + if (this.inContextSignup.isAvailable()) { + const { isSignedIn } = await this.deviceApi.request(new ShowInContextEmailProtectionSignupPromptCall(null)) + // On Android we can't get the input type data again without + // refreshing the page, so instead we can mutate it now that we + // know the user has Email Protection available. + if (this.globalConfig.availableInputTypes) { + this.globalConfig.availableInputTypes.email = isSignedIn + } + this.updateForStateChange() + this.onFinishedAutofill() + } return window.EmailInterface.showTooltip() }, 'getAliasResponse') return alias @@ -45,7 +60,7 @@ class AndroidInterface extends InterfacePrototype { } async setupAutofill () { - + await this.inContextSignup.init() } /** @@ -102,6 +117,14 @@ class AndroidInterface extends InterfacePrototype { } } + /** + * Used by the email web app + * Provides functionality to close the window after in-context sign-up or sign-in + */ + closeEmailProtection () { + this.deviceApi.request(new CloseEmailProtectionTabCall(null)) + } + addLogoutListener (handler) { // Only deal with logging out if we're in the email web app if (!this.globalConfig.isDDGDomain) return diff --git a/src/DeviceInterface/initFormSubmissionsApi.js b/src/DeviceInterface/initFormSubmissionsApi.js index 91d2c9c03..7b5b7cfa4 100644 --- a/src/DeviceInterface/initFormSubmissionsApi.js +++ b/src/DeviceInterface/initFormSubmissionsApi.js @@ -24,7 +24,7 @@ export function initFormSubmissionsApi (forms, matching) { const focusedForm = [...forms.values()].find((form) => form.hasFocus(e)) focusedForm?.submitHandler('global keydown + Enter') } - }) + }, true) /** * Global pointer down events diff --git a/src/DeviceInterface/tests/AndroidInterface.test.js b/src/DeviceInterface/tests/AndroidInterface.test.js index cdbb90478..1ea8c9c77 100644 --- a/src/DeviceInterface/tests/AndroidInterface.test.js +++ b/src/DeviceInterface/tests/AndroidInterface.test.js @@ -7,12 +7,21 @@ import {DeviceApi} from '../../../packages/device-api/index.js' describe('AndroidInterface', function () { beforeEach(() => { require('../../requestIdleCallback.js') + // @ts-ignore + window.BrowserAutofill = { + getIncontextSignupDismissedAt: () => { + window.postMessage(JSON.stringify({ + type: 'getIncontextSignupDismissedAt', + success: {} + }), window.origin) + } + } }) - it('can be instantiated without throwing', () => { + it('can be instantiated without throwing', async () => { const config = createGlobalConfig() const ioHandler = new DeviceApi(new AndroidTransport(config)) const settings = new Settings(config, ioHandler) const device = new AndroidInterface(config, ioHandler, settings) - device.init() + await device.init() }) }) diff --git a/src/deviceApiCalls/__generated__/deviceApiCalls.js b/src/deviceApiCalls/__generated__/deviceApiCalls.js index 7d8ff611e..0f4530d5d 100644 --- a/src/deviceApiCalls/__generated__/deviceApiCalls.js +++ b/src/deviceApiCalls/__generated__/deviceApiCalls.js @@ -21,7 +21,8 @@ import { emailProtectionGetUserDataResultSchema, emailProtectionGetCapabilitiesResultSchema, emailProtectionGetAddressesResultSchema, - emailProtectionRefreshPrivateAddressResultSchema + emailProtectionRefreshPrivateAddressResultSchema, + showInContextEmailProtectionSignupPromptSchema } from "./validators.zod.js" import { DeviceApiCall } from "../../../packages/device-api"; @@ -222,4 +223,12 @@ export class StartEmailProtectionSignupCall extends DeviceApiCall { */ export class CloseEmailProtectionTabCall extends DeviceApiCall { method = "closeEmailProtectionTab" +} +/** + * @extends {DeviceApiCall} + */ +export class ShowInContextEmailProtectionSignupPromptCall extends DeviceApiCall { + method = "ShowInContextEmailProtectionSignupPrompt" + id = "ShowInContextEmailProtectionSignupPromptResponse" + resultValidator = showInContextEmailProtectionSignupPromptSchema } \ No newline at end of file diff --git a/src/deviceApiCalls/__generated__/validators-ts.ts b/src/deviceApiCalls/__generated__/validators-ts.ts index 59e2bd1e6..e7d256a91 100644 --- a/src/deviceApiCalls/__generated__/validators-ts.ts +++ b/src/deviceApiCalls/__generated__/validators-ts.ts @@ -225,6 +225,14 @@ export interface API { closeEmailProtectionTab?: { [k: string]: unknown; }; + /** + * Used by Android to open the in-context signup prompt and report back when completed + */ + ShowInContextEmailProtectionSignupPrompt?: { + id?: "ShowInContextEmailProtectionSignupPromptResponse"; + resultValidator?: ShowInContextEmailProtectionSignupPrompt; + [k: string]: unknown; + }; } /** * Parameters for the addDebugFlag method @@ -661,3 +669,11 @@ export interface EmailProtectionRefreshPrivateAddressResult { }; error?: GenericError; } +/** + * Gets the result of the in-context signup flow + */ +export interface ShowInContextEmailProtectionSignupPrompt { + success: { + isSignedIn: boolean; + }; +} diff --git a/src/deviceApiCalls/__generated__/validators.zod.js b/src/deviceApiCalls/__generated__/validators.zod.js index 59ae3a337..58d78bfc0 100644 --- a/src/deviceApiCalls/__generated__/validators.zod.js +++ b/src/deviceApiCalls/__generated__/validators.zod.js @@ -70,6 +70,12 @@ export const emailProtectionStoreUserDataParamsSchema = z.object({ cohort: z.string() }); +export const showInContextEmailProtectionSignupPromptSchema = z.object({ + success: z.object({ + isSignedIn: z.boolean() + }) +}); + export const generatedPasswordSchema = z.object({ value: z.string(), username: z.string() @@ -417,5 +423,9 @@ export const apiSchema = z.object({ resultValidator: emailProtectionRefreshPrivateAddressResultSchema.optional() })).optional(), startEmailProtectionSignup: z.record(z.unknown()).optional(), - closeEmailProtectionTab: z.record(z.unknown()).optional() + closeEmailProtectionTab: z.record(z.unknown()).optional(), + ShowInContextEmailProtectionSignupPrompt: z.record(z.unknown()).and(z.object({ + id: z.literal("ShowInContextEmailProtectionSignupPromptResponse").optional(), + resultValidator: showInContextEmailProtectionSignupPromptSchema.optional() + })).optional() }); diff --git a/src/deviceApiCalls/api.json b/src/deviceApiCalls/api.json index 71c36d164..fb0fe14b3 100644 --- a/src/deviceApiCalls/api.json +++ b/src/deviceApiCalls/api.json @@ -203,6 +203,14 @@ "closeEmailProtectionTab": { "type": "object", "description": "Used by macOS to close the Email Protection tab after successful in-context sign-up or login" + }, + "ShowInContextEmailProtectionSignupPrompt": { + "type": "object", + "description": "Used by Android to open the in-context signup prompt and report back when completed", + "properties": { + "id": { "type": "string", "const": "ShowInContextEmailProtectionSignupPromptResponse"}, + "resultValidator": { "$ref": "./schemas/showInContextEmailProtectionSignupPrompt.result.json" } + } } } } diff --git a/src/deviceApiCalls/schemas/showInContextEmailProtectionSignupPrompt.result.json b/src/deviceApiCalls/schemas/showInContextEmailProtectionSignupPrompt.result.json new file mode 100644 index 000000000..ad56518aa --- /dev/null +++ b/src/deviceApiCalls/schemas/showInContextEmailProtectionSignupPrompt.result.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ShowInContextEmailProtectionSignupPrompt", + "type": "object", + "description": "Gets the result of the in-context signup flow", + "additionalProperties": false, + "properties": { + "success": { + "type": "object", + "additionalProperties": false, + "properties": { + "isSignedIn": { + "type": "boolean" + } + }, + "required": [ + "isSignedIn" + ] + } + }, + "required": [ + "success" + ] +} \ No newline at end of file diff --git a/src/deviceApiCalls/transports/android.transport.js b/src/deviceApiCalls/transports/android.transport.js index 2823f4182..d3464bb21 100644 --- a/src/deviceApiCalls/transports/android.transport.js +++ b/src/deviceApiCalls/transports/android.transport.js @@ -1,8 +1,13 @@ import {DeviceApiTransport} from '../../../packages/device-api/index.js' import { + CloseEmailProtectionTabCall, GetAutofillDataCall, GetAvailableInputTypesCall, + GetIncontextSignupDismissedAtCall, GetRuntimeConfigurationCall, + SetIncontextSignupPermanentlyDismissedAtCall, + ShowInContextEmailProtectionSignupPromptCall, + StartEmailProtectionSignupCall, StoreFormDataCall } from '../__generated__/deviceApiCalls.js' @@ -37,13 +42,37 @@ export class AndroidTransport extends DeviceApiTransport { return androidSpecificAvailableInputTypes(this.config) } + if (deviceApiCall instanceof GetIncontextSignupDismissedAtCall) { + window.BrowserAutofill.getIncontextSignupDismissedAt(JSON.stringify(deviceApiCall.params)) + return waitForResponse(deviceApiCall.id, this.config) + } + + if (deviceApiCall instanceof SetIncontextSignupPermanentlyDismissedAtCall) { + return window.BrowserAutofill.setIncontextSignupPermanentlyDismissedAt(JSON.stringify(deviceApiCall.params)) + } + + if (deviceApiCall instanceof StartEmailProtectionSignupCall) { + return window.BrowserAutofill.startEmailProtectionSignup(JSON.stringify(deviceApiCall.params)) + } + + if (deviceApiCall instanceof CloseEmailProtectionTabCall) { + return window.BrowserAutofill.closeEmailProtectionTab(JSON.stringify(deviceApiCall.params)) + } + + if (deviceApiCall instanceof ShowInContextEmailProtectionSignupPromptCall) { + window.BrowserAutofill.showInContextEmailProtectionSignupPrompt(JSON.stringify(deviceApiCall.params)) + return waitForResponse(deviceApiCall.id, this.config) + } + if (deviceApiCall instanceof GetAutofillDataCall) { window.BrowserAutofill.getAutofillData(JSON.stringify(deviceApiCall.params)) return waitForResponse(deviceApiCall.id, this.config) } + if (deviceApiCall instanceof StoreFormDataCall) { return window.BrowserAutofill.storeFormData(JSON.stringify(deviceApiCall.params)) } + throw new Error('android: not implemented: ' + deviceApiCall.method) } } diff --git a/swift-package/Resources/assets/autofill-debug.js b/swift-package/Resources/assets/autofill-debug.js index 5ff88f0a3..5875c2c2a 100644 --- a/swift-package/Resources/assets/autofill-debug.js +++ b/swift-package/Resources/assets/autofill-debug.js @@ -7110,8 +7110,11 @@ var _InterfacePrototype = _interopRequireDefault(require("./InterfacePrototype.j var _autofillUtils = require("../autofill-utils.js"); var _NativeUIController = require("../UI/controllers/NativeUIController.js"); var _appleUtils = require("@duckduckgo/content-scope-scripts/src/apple-utils"); +var _InContextSignup = require("../InContextSignup.js"); +var _deviceApiCalls = require("../deviceApiCalls/__generated__/deviceApiCalls.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class AndroidInterface extends _InterfacePrototype.default { + inContextSignup = new _InContextSignup.InContextSignup(this); async isEnabled() { return (0, _autofillUtils.autofillEnabled)(this.globalConfig, _appleUtils.processConfig); } @@ -7122,7 +7125,20 @@ class AndroidInterface extends _InterfacePrototype.default { async getAlias() { const { alias - } = await (0, _autofillUtils.sendAndWaitForAnswer)(() => { + } = await (0, _autofillUtils.sendAndWaitForAnswer)(async () => { + if (this.inContextSignup.isAvailable()) { + const { + isSignedIn + } = await this.deviceApi.request(new _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall(null)); + // On Android we can't get the input type data again without + // refreshing the page, so instead we can mutate it now that we + // know the user has Email Protection available. + if (this.globalConfig.availableInputTypes) { + this.globalConfig.availableInputTypes.email = isSignedIn; + } + this.updateForStateChange(); + this.onFinishedAutofill(); + } return window.EmailInterface.showTooltip(); }, 'getAliasResponse'); return alias; @@ -7153,7 +7169,9 @@ class AndroidInterface extends _InterfacePrototype.default { // ...on other domains we assume true because the script wouldn't exist otherwise return true; } - async setupAutofill() {} + async setupAutofill() { + await this.inContextSignup.init(); + } /** * Used by the email web app @@ -7210,6 +7228,14 @@ class AndroidInterface extends _InterfacePrototype.default { } } } + + /** + * Used by the email web app + * Provides functionality to close the window after in-context sign-up or sign-in + */ + closeEmailProtection() { + this.deviceApi.request(new _deviceApiCalls.CloseEmailProtectionTabCall(null)); + } addLogoutListener(handler) { // Only deal with logging out if we're in the email web app if (!this.globalConfig.isDDGDomain) return; @@ -7225,7 +7251,7 @@ class AndroidInterface extends _InterfacePrototype.default { } exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],24:[function(require,module,exports){ +},{"../InContextSignup.js":44,"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9240,7 +9266,7 @@ function initFormSubmissionsApi(forms, matching) { const focusedForm = [...forms.values()].find(form => form.hasFocus(e)); focusedForm?.submitHandler('global keydown + Enter'); } - }); + }, true); /** * Global pointer down events @@ -16543,7 +16569,7 @@ const constants = exports.constants = { Object.defineProperty(exports, "__esModule", { value: true }); -exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; +exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.ShowInContextEmailProtectionSignupPromptCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; var _validatorsZod = require("./validators.zod.js"); var _deviceApi = require("../../../packages/device-api"); /* DO NOT EDIT, this file was generated by scripts/api-call-generator.js */ @@ -16772,7 +16798,16 @@ exports.StartEmailProtectionSignupCall = StartEmailProtectionSignupCall; class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { method = "closeEmailProtectionTab"; } +/** + * @extends {DeviceApiCall} + */ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; +class ShowInContextEmailProtectionSignupPromptCall extends _deviceApi.DeviceApiCall { + method = "ShowInContextEmailProtectionSignupPrompt"; + id = "ShowInContextEmailProtectionSignupPromptResponse"; + resultValidator = _validatorsZod.showInContextEmailProtectionSignupPromptSchema; +} +exports.ShowInContextEmailProtectionSignupPromptCall = ShowInContextEmailProtectionSignupPromptCall; },{"../../../packages/device-api":12,"./validators.zod.js":66}],66:[function(require,module,exports){ "use strict"; @@ -16780,7 +16815,7 @@ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; Object.defineProperty(exports, "__esModule", { value: true }); -exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; +exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.showInContextEmailProtectionSignupPromptSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; var _zod = require("zod"); /* DO NOT EDIT, this file was generated by scripts/api-call-generator.js */ // Generated by ts-to-zod @@ -16843,6 +16878,11 @@ const emailProtectionStoreUserDataParamsSchema = exports.emailProtectionStoreUse userName: _zod.z.string(), cohort: _zod.z.string() }); +const showInContextEmailProtectionSignupPromptSchema = exports.showInContextEmailProtectionSignupPromptSchema = _zod.z.object({ + success: _zod.z.object({ + isSignedIn: _zod.z.boolean() + }) +}); const generatedPasswordSchema = exports.generatedPasswordSchema = _zod.z.object({ value: _zod.z.string(), username: _zod.z.string() @@ -17163,7 +17203,11 @@ const apiSchema = exports.apiSchema = _zod.z.object({ resultValidator: emailProtectionRefreshPrivateAddressResultSchema.optional() })).optional(), startEmailProtectionSignup: _zod.z.record(_zod.z.unknown()).optional(), - closeEmailProtectionTab: _zod.z.record(_zod.z.unknown()).optional() + closeEmailProtectionTab: _zod.z.record(_zod.z.unknown()).optional(), + ShowInContextEmailProtectionSignupPrompt: _zod.z.record(_zod.z.unknown()).and(_zod.z.object({ + id: _zod.z.literal("ShowInContextEmailProtectionSignupPromptResponse").optional(), + resultValidator: showInContextEmailProtectionSignupPromptSchema.optional() + })).optional() }); },{"zod":9}],67:[function(require,module,exports){ @@ -17229,6 +17273,23 @@ class AndroidTransport extends _index.DeviceApiTransport { if (deviceApiCall instanceof _deviceApiCalls.GetAvailableInputTypesCall) { return androidSpecificAvailableInputTypes(this.config); } + if (deviceApiCall instanceof _deviceApiCalls.GetIncontextSignupDismissedAtCall) { + window.BrowserAutofill.getIncontextSignupDismissedAt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } + if (deviceApiCall instanceof _deviceApiCalls.SetIncontextSignupPermanentlyDismissedAtCall) { + return window.BrowserAutofill.setIncontextSignupPermanentlyDismissedAt(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.StartEmailProtectionSignupCall) { + return window.BrowserAutofill.startEmailProtectionSignup(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.CloseEmailProtectionTabCall) { + return window.BrowserAutofill.closeEmailProtectionTab(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall) { + window.BrowserAutofill.showInContextEmailProtectionSignupPrompt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } if (deviceApiCall instanceof _deviceApiCalls.GetAutofillDataCall) { window.BrowserAutofill.getAutofillData(JSON.stringify(deviceApiCall.params)); return waitForResponse(deviceApiCall.id, this.config); diff --git a/swift-package/Resources/assets/autofill.js b/swift-package/Resources/assets/autofill.js index e9bd2867c..f8f022768 100644 --- a/swift-package/Resources/assets/autofill.js +++ b/swift-package/Resources/assets/autofill.js @@ -3165,8 +3165,11 @@ var _InterfacePrototype = _interopRequireDefault(require("./InterfacePrototype.j var _autofillUtils = require("../autofill-utils.js"); var _NativeUIController = require("../UI/controllers/NativeUIController.js"); var _appleUtils = require("@duckduckgo/content-scope-scripts/src/apple-utils"); +var _InContextSignup = require("../InContextSignup.js"); +var _deviceApiCalls = require("../deviceApiCalls/__generated__/deviceApiCalls.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class AndroidInterface extends _InterfacePrototype.default { + inContextSignup = new _InContextSignup.InContextSignup(this); async isEnabled() { return (0, _autofillUtils.autofillEnabled)(this.globalConfig, _appleUtils.processConfig); } @@ -3177,7 +3180,20 @@ class AndroidInterface extends _InterfacePrototype.default { async getAlias() { const { alias - } = await (0, _autofillUtils.sendAndWaitForAnswer)(() => { + } = await (0, _autofillUtils.sendAndWaitForAnswer)(async () => { + if (this.inContextSignup.isAvailable()) { + const { + isSignedIn + } = await this.deviceApi.request(new _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall(null)); + // On Android we can't get the input type data again without + // refreshing the page, so instead we can mutate it now that we + // know the user has Email Protection available. + if (this.globalConfig.availableInputTypes) { + this.globalConfig.availableInputTypes.email = isSignedIn; + } + this.updateForStateChange(); + this.onFinishedAutofill(); + } return window.EmailInterface.showTooltip(); }, 'getAliasResponse'); return alias; @@ -3208,7 +3224,9 @@ class AndroidInterface extends _InterfacePrototype.default { // ...on other domains we assume true because the script wouldn't exist otherwise return true; } - async setupAutofill() {} + async setupAutofill() { + await this.inContextSignup.init(); + } /** * Used by the email web app @@ -3265,6 +3283,14 @@ class AndroidInterface extends _InterfacePrototype.default { } } } + + /** + * Used by the email web app + * Provides functionality to close the window after in-context sign-up or sign-in + */ + closeEmailProtection() { + this.deviceApi.request(new _deviceApiCalls.CloseEmailProtectionTabCall(null)); + } addLogoutListener(handler) { // Only deal with logging out if we're in the email web app if (!this.globalConfig.isDDGDomain) return; @@ -3280,7 +3306,7 @@ class AndroidInterface extends _InterfacePrototype.default { } exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],14:[function(require,module,exports){ +},{"../InContextSignup.js":34,"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],14:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5295,7 +5321,7 @@ function initFormSubmissionsApi(forms, matching) { const focusedForm = [...forms.values()].find(form => form.hasFocus(e)); focusedForm?.submitHandler('global keydown + Enter'); } - }); + }, true); /** * Global pointer down events @@ -12598,7 +12624,7 @@ const constants = exports.constants = { Object.defineProperty(exports, "__esModule", { value: true }); -exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; +exports.StoreFormDataCall = exports.StartEmailProtectionSignupCall = exports.ShowInContextEmailProtectionSignupPromptCall = exports.SetSizeCall = exports.SetIncontextSignupPermanentlyDismissedAtCall = exports.SendJSPixelCall = exports.SelectedDetailCall = exports.OpenManagePasswordsCall = exports.OpenManageIdentitiesCall = exports.OpenManageCreditCardsCall = exports.GetRuntimeConfigurationCall = exports.GetIncontextSignupDismissedAtCall = exports.GetAvailableInputTypesCall = exports.GetAutofillInitDataCall = exports.GetAutofillDataCall = exports.GetAutofillCredentialsCall = exports.EmailProtectionStoreUserDataCall = exports.EmailProtectionRemoveUserDataCall = exports.EmailProtectionRefreshPrivateAddressCall = exports.EmailProtectionGetUserDataCall = exports.EmailProtectionGetIsLoggedInCall = exports.EmailProtectionGetCapabilitiesCall = exports.EmailProtectionGetAddressesCall = exports.CloseEmailProtectionTabCall = exports.CloseAutofillParentCall = exports.CheckCredentialsProviderStatusCall = exports.AskToUnlockProviderCall = exports.AddDebugFlagCall = void 0; var _validatorsZod = require("./validators.zod.js"); var _deviceApi = require("../../../packages/device-api"); /* DO NOT EDIT, this file was generated by scripts/api-call-generator.js */ @@ -12827,7 +12853,16 @@ exports.StartEmailProtectionSignupCall = StartEmailProtectionSignupCall; class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { method = "closeEmailProtectionTab"; } +/** + * @extends {DeviceApiCall} + */ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; +class ShowInContextEmailProtectionSignupPromptCall extends _deviceApi.DeviceApiCall { + method = "ShowInContextEmailProtectionSignupPrompt"; + id = "ShowInContextEmailProtectionSignupPromptResponse"; + resultValidator = _validatorsZod.showInContextEmailProtectionSignupPromptSchema; +} +exports.ShowInContextEmailProtectionSignupPromptCall = ShowInContextEmailProtectionSignupPromptCall; },{"../../../packages/device-api":2,"./validators.zod.js":56}],56:[function(require,module,exports){ "use strict"; @@ -12835,7 +12870,7 @@ exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; Object.defineProperty(exports, "__esModule", { value: true }); -exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; +exports.userPreferencesSchema = exports.triggerContextSchema = exports.storeFormDataSchema = exports.showInContextEmailProtectionSignupPromptSchema = exports.setSizeParamsSchema = exports.setIncontextSignupPermanentlyDismissedAtSchema = exports.sendJSPixelParamsSchema = exports.selectedDetailParamsSchema = exports.runtimeConfigurationSchema = exports.providerStatusUpdatedSchema = exports.outgoingCredentialsSchema = exports.getRuntimeConfigurationResponseSchema = exports.getIncontextSignupDismissedAtSchema = exports.getAvailableInputTypesResultSchema = exports.getAutofillInitDataResponseSchema = exports.getAutofillDataResponseSchema = exports.getAutofillDataRequestSchema = exports.getAutofillCredentialsResultSchema = exports.getAutofillCredentialsParamsSchema = exports.getAliasResultSchema = exports.getAliasParamsSchema = exports.genericErrorSchema = exports.generatedPasswordSchema = exports.emailProtectionStoreUserDataParamsSchema = exports.emailProtectionRefreshPrivateAddressResultSchema = exports.emailProtectionGetUserDataResultSchema = exports.emailProtectionGetIsLoggedInResultSchema = exports.emailProtectionGetCapabilitiesResultSchema = exports.emailProtectionGetAddressesResultSchema = exports.credentialsSchema = exports.contentScopeSchema = exports.checkCredentialsProviderStatusResultSchema = exports.availableInputTypesSchema = exports.availableInputTypes1Schema = exports.autofillSettingsSchema = exports.autofillFeatureTogglesSchema = exports.askToUnlockProviderResultSchema = exports.apiSchema = exports.addDebugFlagParamsSchema = void 0; const sendJSPixelParamsSchema = exports.sendJSPixelParamsSchema = null; const addDebugFlagParamsSchema = exports.addDebugFlagParamsSchema = null; const getAutofillCredentialsParamsSchema = exports.getAutofillCredentialsParamsSchema = null; @@ -12846,6 +12881,7 @@ const getIncontextSignupDismissedAtSchema = exports.getIncontextSignupDismissedA const getAliasParamsSchema = exports.getAliasParamsSchema = null; const getAliasResultSchema = exports.getAliasResultSchema = null; const emailProtectionStoreUserDataParamsSchema = exports.emailProtectionStoreUserDataParamsSchema = null; +const showInContextEmailProtectionSignupPromptSchema = exports.showInContextEmailProtectionSignupPromptSchema = null; const generatedPasswordSchema = exports.generatedPasswordSchema = null; const triggerContextSchema = exports.triggerContextSchema = null; const credentialsSchema = exports.credentialsSchema = null; @@ -12938,6 +12974,23 @@ class AndroidTransport extends _index.DeviceApiTransport { if (deviceApiCall instanceof _deviceApiCalls.GetAvailableInputTypesCall) { return androidSpecificAvailableInputTypes(this.config); } + if (deviceApiCall instanceof _deviceApiCalls.GetIncontextSignupDismissedAtCall) { + window.BrowserAutofill.getIncontextSignupDismissedAt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } + if (deviceApiCall instanceof _deviceApiCalls.SetIncontextSignupPermanentlyDismissedAtCall) { + return window.BrowserAutofill.setIncontextSignupPermanentlyDismissedAt(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.StartEmailProtectionSignupCall) { + return window.BrowserAutofill.startEmailProtectionSignup(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.CloseEmailProtectionTabCall) { + return window.BrowserAutofill.closeEmailProtectionTab(JSON.stringify(deviceApiCall.params)); + } + if (deviceApiCall instanceof _deviceApiCalls.ShowInContextEmailProtectionSignupPromptCall) { + window.BrowserAutofill.showInContextEmailProtectionSignupPrompt(JSON.stringify(deviceApiCall.params)); + return waitForResponse(deviceApiCall.id, this.config); + } if (deviceApiCall instanceof _deviceApiCalls.GetAutofillDataCall) { window.BrowserAutofill.getAutofillData(JSON.stringify(deviceApiCall.params)); return waitForResponse(deviceApiCall.id, this.config); diff --git a/types.d.ts b/types.d.ts index 32e64644d..02d8bc8cf 100644 --- a/types.d.ts +++ b/types.d.ts @@ -39,6 +39,11 @@ interface Window { BrowserAutofill: { getAutofillData(data: string): void; storeFormData(data: string): void; + getIncontextSignupDismissedAt(data: string): void; + setIncontextSignupPermanentlyDismissedAt(data: string): void; + showInContextEmailProtectionSignupPrompt(data: string): void; + startEmailProtectionSignup(data: string): void; + closeEmailProtectionTab(data: string): void; } // Used in Apple apps