Skip to content

Commit

Permalink
Revert "Android: enable iframe support (#536)"
Browse files Browse the repository at this point in the history
This reverts commit 8b046b1, disabling
Android iframe support due to a bug in the native WebView. See
https://app.asana.com/0/1203822806345703/1207304124810216/f for details.
  • Loading branch information
sjbarag committed Jun 20, 2024
1 parent 5e15154 commit 0ff72f6
Show file tree
Hide file tree
Showing 36 changed files with 1,741 additions and 2,200 deletions.
662 changes: 289 additions & 373 deletions dist/autofill-debug.js

Large diffs are not rendered by default.

613 changes: 272 additions & 341 deletions dist/autofill.js

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions docs/playwright-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@ await emailPage.clickIntoInput()

```shell
npm run test:integration
# Shows the UI, thus allowing await page.pause()
npm run test:integration:showui
# Skips file compilation and uses higher concurrency
npm run test:integration:fast
# Skips file compilation and uses higher concurrency, and shows the UI
npm run test:integration:fast:showui
```

## Running only flaky tests
Expand Down
177 changes: 94 additions & 83 deletions docs/runtime.android.md
Original file line number Diff line number Diff line change
@@ -1,110 +1,121 @@
## String replacement
On Android, the only string replacement needed is the platform name. We substitute this:
## ~`getRuntimeConfiguration()`~

```js
// INJECT userPreferences HERE
```
on android devices, this data is retrieved from the following string-replacements:

with this
Internally, we force it into the following shape in order to conform to the following schema definition:
- [Runtime Configuration Schema](https://github.com/duckduckgo/content-scope-scripts/blob/shane/unify-config/src/schema/runtime-configuration.schema.json)

```js
userPreferences = {
"debug": false,
"platform": {
"name": "android"
}
}
**strings to replace**
```
// INJECT contentScope HERE
// INJECT userUnprotectedDomains HERE
// INJECT userPreferences HERE
```

## `getRuntimeConfiguration()`
Directly replace the lines above in the following way:

See: [../src/schema/runtimeConfiguration.json](../src/deviceApiCalls/schemas/runtimeConfiguration.json).
`str.replace('// INJECT contentScope HERE', 'contentScope = {JSON_HERE}') + ';'`

This includes the configurations needed for autofill to know what options are available on the specific page we're on, for example whether the domain is blocklisted by remote config, or whether a specific feature is turned on/off either remotely or by the user.
For example, the 3 variables should look like this (don't forget the semicolon at the end of each!)

Compared to other platforms, on Android we include `availableInputTypes` in the initial runtime configuration. We plan to adopt this to all platforms to reduce message passing.
```javascript
// INJECT contentScope HERE
contentScope = {
"features": {
"autofill": {
"state": "enabled",
"exceptions": []
}
},
"unprotectedTemporary": []
};
```

**Example:**
```javascript
// INJECT userUnprotectedDomains HERE
userUnprotectedDomains = [];
```

```json
{
"success": {
"availableInputTypes": {
"email": false,
"credentials": {
"username": true,
"password": true
},
"identities": {
"firstName": false,
"middleName": false,
"lastName": false,
"birthdayDay": false,
"birthdayMonth": false,
"birthdayYear": false,
"addressStreet": false,
"addressStreet2": false,
"addressCity": false,
"addressProvince": false,
"addressPostalCode": false,
"addressCountryCode": false,
"phone": false,
"emailAddress": false
},
"creditCards": {
"cardName": false,
"cardSecurityCode": false,
"expirationMonth": false,
"expirationYear": false,
"cardNumber": false
}
},
"contentScope": {
"features": {
"autofill": {
"state": "enabled",
"exceptions": []
}
},
"unprotectedTemporary": []
},
"userUnprotectedDomains": [],
"userPreferences": {
"debug": false,
"platform": {
"name": "android"
},
"features": {
"autofill": {
"settings": {
"featureToggles": {
"inputType_credentials": true,
"inputType_identities": false,
"inputType_creditCards": false,
"emailProtection": true,
"password_generation": true,
"credentials_saving": true
}
}
```javascript
// INJECT userPreferences HERE
userPreferences = {
"debug": false,
"platform": {
"name": "android"
},
"features": {
"autofill": {
"settings": {
"featureToggles": {
"inputType_credentials": true,
"inputType_identities": false,
"inputType_creditCards": false,
"emailProtection": true,
"password_generation": false,
"credentials_saving": true
}
}
}
}
}
};
```

---

## `getAvailableInputTypes()`

This represents which input types we can autofill for the current user.


**strings to replace**
```
// INJECT availableInputTypes HERE
```

Directly replace the line above in the following way:

`str.replace('// INJECT availableInputTypes HERE', 'contentScope = {JSON_HERE}') + ';'`

See: [../src/schema/availableInputTypes.json](../src/deviceApiCalls/schemas/availableInputTypes.json).

This represents which input types we can autofill for the current user. Values are `true` if we can autofill the
field type with at least one item. For example, if we have two credential items and the first only has a username
and the second only has a password, both fields will be `true`. The email value is the same as returned by the
and the second only has a password, both fields will be `true`. The email value is the same as returned by the
`isSignedIn()` method. At this time `identities` and `creditCards` are optional as they are not supported on Android.

On Android, this data is passed with the initial runtime configurations, so the call just returns the data we already received.
```javascript
// INJECT availableInputTypes HERE
availableInputTypes = {
"email": true,
"credentials": {
"username": true,
"password": true
},
"identities": {
"firstName": false,
"middleName": false,
"lastName": false,
"birthdayDay": false,
"birthdayMonth": false,
"birthdayYear": false,
"addressStreet": false,
"addressStreet2": false,
"addressCity": false,
"addressProvince": false,
"addressPostalCode": false,
"addressCountryCode": false,
"phone": false,
"emailAddress": false
},
"creditCards": {
"cardName": false,
"cardSecurityCode": false,
"expirationMonth": false,
"expirationYear": false,
"cardNumber": false
}
}
```

---

Expand Down Expand Up @@ -154,11 +165,11 @@ window.BrowserAutofill.storeFormData(JSON.stringify(data))

---

## `window.ddgGetAutofillData(request)`
## `window.BrowserAutofill.getAutofillData(request)`

- Autofill will send `request` as a string of JSON
- See: [../src/schema/request.getAutofillData.schema.json](../src/deviceApiCalls/schemas/getAutofillData.params.json)
- Response Message via the listener to: `window.ddgGetAutofillData`
- Response Message via: `window.postMessage(response)`
- See: [../src/schema/response.getAutofillData.schema.json](../src/deviceApiCalls/schemas/getAutofillData.result.json)

**`request`** example
Expand Down
102 changes: 52 additions & 50 deletions docs/runtime.ios.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,74 @@
## String replacement
On iOS and macOS, we string-replace these variables:
## ~`getRuntimeConfiguration()`~

on Apple devices, this data is retrieved from the following string-replacements

- [BrowserServices Kit String replacements](https://github.com/duckduckgo/BrowserServicesKit/blob/main/Sources/BrowserServicesKit/Autofill/AutofillUserScript+SourceProvider.swift#L54-L56)

```js
Internally, we force it into the following shape in order to conform to the following schema definition:
- [Runtime Configuration Schema](https://github.com/duckduckgo/content-scope-scripts/blob/shane/unify-config/src/schema/runtime-configuration.schema.json)

**strings to replace**
```
// INJECT contentScope HERE
// INJECT userUnprotectedDomains HERE
// INJECT userPreferences HERE
// INJECT isApp HERE
// INJECT isTopFrame HERE
// INJECT supportsTopFrame HERE
// INJECT hasModernWebkitAPI HERE
// INJECT webkitMessageHandlerNames HERE
```

- `userPreferences`: sets the platform name
- `isApp`: true when is macOS
- `isTopFrame`: true when the script is being rendered in the overlay webview
- `supportsTopFrame`: true on macOS when the overlay webview is supported (now on all versions)
- `hasModernWebkitAPI`: now true on all versions, since we've dropped macOS Catalina
- `webkitMessageHandlerNames`: an array of all the expected call names, if we attempt a call that's not in the list, the script will error
Directly replace the lines above in the following way:

## ~`getRuntimeConfiguration()`~
`str.replace('// INJECT contentScope HERE', 'contentScope = {JSON_HERE}') + ';'`

See: [../src/schema/runtimeConfiguration.json](../src/deviceApiCalls/schemas/runtimeConfiguration.json).
For example, the 3 variables should look like this (don't forget the semicolon at the end of each!)

This includes the configurations needed for autofill to know what options are available on the specific page we're on, for example whether the domain is blocklisted by remote config, or whether a specific feature is turned on/off either remotely or by the user.
```javascript
// INJECT contentScope HERE
contentScope = {
"features": {
"autofill": {
"state": "enabled",
"exceptions": []
}
},
"unprotectedTemporary": []
};
```

**Example:**
```javascript
// INJECT userUnprotectedDomains HERE
userUnprotectedDomains = [];
```

```json
{
"success": {
"contentScope": {
"features": {
"autofill": {
"state": "enabled",
"exceptions": []
}
},
"unprotectedTemporary": []
},
"userUnprotectedDomains": [],
"userPreferences": {
"debug": false,
"platform": {
"name": "ios"
},
"features": {
"autofill": {
"settings": {
"featureToggles": {
"inputType_credentials": true,
"inputType_identities": false,
"inputType_creditCards": false,
"emailProtection": true,
"password_generation": true,
"credentials_saving": true
}
}
```javascript
// INJECT userPreferences HERE
userPreferences = {
"debug": false,
"platform": {
"name": "android"
},
"features": {
"autofill": {
"settings": {
"featureToggles": {
"inputType_credentials": true,
"inputType_identities": false,
"inputType_creditCards": false,
"emailProtection": true,
"password_generation": false,
"credentials_saving": true
}
}
}
}
}
};
```

---

## `getAvailableInputTypes()`

see: [../src/deviceApiCalls/schemas/getAvailableInputTypes.result.json](../src/deviceApiCalls/schemas/getAvailableInputTypes.result.json)
see:

- [../src/deviceApiCalls/schemas/getAvailableInputTypes.result.json](../src/deviceApiCalls/schemas/getAvailableInputTypes.result.json)

This represents which input types we can autofill for the current user. Values are `true` if we can autofill the
field type with at least one item. For example, if we have two credential items and the first only has a username
Expand Down
16 changes: 1 addition & 15 deletions integration-test/helpers/harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,20 +171,6 @@ export async function defaultIOSScript (page) {
.applyTo(page)
}

/**
* @param {import("@playwright/test").Page} page
*/
export async function defaultAndroidScript (page) {
return createAutofillScript()
.replaceAll({
userPreferences: {
platform: {name: 'android'}
}
})
.platform('android')
.applyTo(page)
}

/**
* @param {import("@playwright/test").Page} page
*/
Expand Down Expand Up @@ -327,7 +313,7 @@ export async function addMocksAsAttachments (page, test, testInfo) {
const lines = [`name: ${name}`]
if (platform === 'android') {
lines.push('sent as json string: \n\n' + JSON.stringify(params))
params = typeof params === 'string' ? JSON.parse(/** @type {any} */(params)) : params
params = JSON.parse(/** @type {any} */(params))
}
lines.push(`\n\nparams: \n\n` + JSON.stringify(params, null, 2))
lines.push(`\n\nresponse: \n\n` + JSON.stringify(response, null, 2))
Expand Down
1 change: 0 additions & 1 deletion integration-test/helpers/harness.types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ interface CredentialsMock {
* ```
*/
interface MockBuilder<State, Mocks extends Record<string, any>> {
withRuntimeConfigOverrides(overrides: RuntimeConfiguration): MockBuilder<State, Mocks>
// Set the private email address
withPrivateEmail(email: string): MockBuilder<State, Mocks>
// Set the personal email address
Expand Down
Loading

0 comments on commit 0ff72f6

Please sign in to comment.