-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue/126 - Android Autofill #141
Issue/126 - Android Autofill #141
Conversation
…etect HTML based inputs
…ues, add Web Domain in results
…ying credentials across to Android AutoFill service
…utofill on Android
…th Android sharing redux state between main app and autofill app.
… with new ReactNativeHost instance
@perry-mitchell This PR is no longer a WIP - its now ready for testing and hopefully merging! |
android/app/build.gradle
Outdated
release { | ||
manifestPlaceholders = [usesCleartextTraffic:"true"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've not done much Android or React Native development, but is it normal that a password manager needs to enable non-HTTPS communication? Do you know what plaintext HTTP resources this app requests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good find @jokeyrhyme! Cleartext was needed to allow access to the metro bundler in dev - I must have forgotten to switch it back to off for release.
This is fixed in feccc8a
Hmmm, the build is failing, which seems normal for this project: https://travis-ci.org/buttercup/buttercup-mobile/builds/494137819 However, previously, the "Node.js:8" job was passing: https://travis-ci.org/buttercup/buttercup-mobile/builds/481638329 The rest of this looks fine to me (for what it's worth) :) |
@jokeyrhyme I've fixed the nodejs test, but after a few attempts was not able to get iOS and Android tests to work. The tests we're already failing before I came along, and I'm not all that familiar with travis, so I'll defer fixing those to someone with more experience. |
@se1exin fair enough, yeah, looks good :) |
Yeah the tests are a mess.. they pass locally but the CIs seem to have major issues. That's a separate issue 😅
Amazing! I'll make sure it's taken care of this week! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a couple of minor items!
export function autoFillEnabledForSource(sourceID) { | ||
return new Promise((resolve, reject) => { | ||
if (autoFillAvailable) { | ||
return AutoFillBridge.getAutoFillEnabledSources().then(autoFillSources => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this too.. Otherwise perhaps wrapping it in something like:
return Promise.resolve()
.then(() => {
// ...
return false;
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this one - the promise resolves on all paths, unless I'm missing something?
export function getAutoFillSystemStatus() { | ||
return new Promise((resolve, reject) => { | ||
if (autoFillAvailable) { | ||
return AutoFillBridge.getAutoFillSystemStatus().then(isAutoFillEnabled => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again for this one - the promise resolves on all paths, unless I'm missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean it's alright of course, it's just a bit weird seeing the promise being returned when using the new Promise((resolve, reject) => ...
format. I'm fine with this as it works of course.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively (maybe):
export function getAutoFillSystemStatus() {
return autoFillAvailable ? AutoFillBridge.getAutoFillSystemStatus() : Promise.resolve(false);
}
@se1exin Sorry for the delay.. Has been a busy week and I'm recovering from a bug. I'm keen to get this released.. It's a huge PR, and definitely over my head. My idea is that once again, after it's reviewed, I'll merge it to a holding branch where we'll test it before going to master. |
@perry-mitchell all good, hope your feeling better! I've adding the missing resolves (not sure how I missed them originally..), however I'm not sure about the last 2 in the review (see review comments). Happy for you to just re-write the Promise logic for those if your can see an issue that I can't :) |
Thanks @se1exin for this! I've just tested it, and the autofill works great. However I have a slight problem with a few random errors that keep occurring, which Im not sure are caused by this PR. Edit: I have found a few issues:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! Just a slight change needed from my part
const itemSystemSettings = "Android Settings"; | ||
const itemCancel = "Cancel"; | ||
return Promise.all([getAutoFillSystemStatus(), autoFillEnabledForSource(currentSourceID)]).then( | ||
results => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe destructure this instead of assigning new constants later:
results => { | |
([autoFillEnabled, archiveEnabled]) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
export function getAutoFillSystemStatus() { | ||
return new Promise((resolve, reject) => { | ||
if (autoFillAvailable) { | ||
return AutoFillBridge.getAutoFillSystemStatus().then(isAutoFillEnabled => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean it's alright of course, it's just a bit weird seeing the promise being returned when using the new Promise((resolve, reject) => ...
format. I'm fine with this as it works of course.
Hey! @perry-mitchell @sallar Sorry for the delay in getting back to you both on this, work and life has been quite busy for the last few weeks. It also doesn't seem to be easing off so at this point I'm not sure when I will get a chance to address the feedback items sorry. Not sure what I can do to help at the moment but thought I would let you know so your weren't left hanging. |
Thanks @se1exin - We know the feeling! We'll take care of the final adjustments shortly. Take care 👍 |
Great work 👏 ! Can't wait to see this merged! |
Hi great work btw @se1exin ! But how do you retrieve the domain name from browser apps? My machine the getWebDomain() method always return null? |
Hi @lincdh thanks, it's been a few years since I implemented this so my memory isn't very fresh on the inner details, but the first think I would check is your service config contains the apps you want to read from: android/app/src/main/res/xml/autofill_service_configuration.xml Good luck 🙂 |
@se1exin I tried to create another android project to test your code but the same result. Did it looks somewhat like below when you debug?: |
@lincdh Sorry, this isn't the right forum for debugging your project. Please use this codebase as a reference for your work, however. Best of luck :) |
This PR should be considered a Work In Progress for two reasons:
Compared to the iOS implementation and experience, so far Android is only about half way. The simplest form of AutoFill is working - with credentials being offered on-screen in the app being logged-into (e.g. Google Chrome). However, kicking the user temporarily into the Buttercup app to choose a credential (like in the iOS implementation) is not yet implemented, and appears to be a much larger undertaking than it was with iOS. Whilst it should indeed be possible to implement the kick-back to Buttercup to choose an (up-to-date) credential, I thought I would put the PR up in case you wanted to get at least what has been implemented into release soon rather than waiting for the whole thing to be complete.Edit: Point 1 is now working as well
In case you are keen to release based on point 1, there is one other factor to consider first. On Android there is no obvious way (that I can find) to set Butercup to be the AutoFill provider in the Android Settings (which can be a labyrinth at the best of times). The recommended way in the Android dev docs is to request if the user wants to setup autofill, and then programmatically switch to the AutoFill selection settings in the Android Settings app, at which point the user can toggle Buttercup on. I am currently immediately switching directly to the Android Settings page as soon as the app loads, which is obviously a terrible idea, so I would like to formally request for feedback on how, where, and when the app should ask the user if they would like to enable AutoFill. I think this also applies for iOS as well, as currently it is up to the user to manually go and enable AutoFill in the iOS settings.Edit: Point 2 has been implemented using the same approach as enabling Touch ID on an Archive
Finally, I'm also going to suggest that the conversation around point 2 be held in the original issue #126, as I feel it is more likely to be seen and participated by the community there.
Closes #71, Closes #126