-
Notifications
You must be signed in to change notification settings - Fork 616
Fail Firestore client if we can't establish SSL connection #508
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
Conversation
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.
The code lgtm. But are we able to not raise an Internal error in this case? As discussed in standup, those usually imply a bug in our code, and this situation isn't quite that.
We can special-case it here but I personally don't think it's worth it (especially since I don't want to do this for all IllegalStateExceptions): https://github.com/firebase/firebase-android-sdk/blob/master/firebase-firestore/src/main/java/com/google/firebase/firestore/util/AsyncQueue.java#L378 I can be convinced otherwise, but I was hoping that the error message itself addressed the concerns from standup. |
We could also throw on the UI thread, but I reckon that is pretty frowned upon. @samtstern ? |
I updated this PR to crash the UI thread instead. That removes the first part of the stacktrace in the description. Note that I also included EHOSTUNREACH since that is the exception I am getting on my home Wifi. |
@schmidt-sebastian crashing the user's app is very rude especially when:
So I'd say it's not reasonable for us to crash the main thread. Better to just fail every single Firestore call or something like that. |
This is dependent on developer input. Namely, if they want to ship for non-GMS devices prior to Android 5.0, they need to build with Conscript. If there were a way to fail at build time we'd do it. |
@wilhuff I can see that angle, but a lot of times your app "ends up" on those devices against your will. Especially in the markets where non-GMS devices are more prevalent. |
I don't think failing every method is useful:
We don't have any other kind of developer error that fails like this, so implementing error-every-method is pretty expensive. |
I think I am going to defer the final decision on this to the API council. To me, this is akin to a developer not shipping/declaring a required dependency which would also crash the JVM. In the meantime, I will make the check a little tighter and only throw on < API level 21. |
I'd still prefer to avoid surfacing this as an Internal error; I like being able to unconditionally say that all Internal errors represent a bug in our code. Another option might be to introduce a NotOurFaultException (usage: Extending IllegalArgumentException (SslDependencyMissingException?) and then explicitly checking for it could work. (Doesn't solve the generic case, and would involve us introducing at least one new class... more if there are other cases like this in the future.) Plumbing a boolean (ourFault=true) through to the above function would work too... but would be a pain. Not worth it, IMO. I also don't like parsing the IllegalArgumentException message. I like your idea of just crashing the UI thread. If you can get everyone on board with that, it seems simplest. (Code still lgtm.) |
/retest |
@vkryachko approved this for merging in an internal API discussion thread. |
Assigning to @rsgowman for approval. |
firebase-firestore/CHANGELOG.md
Outdated
@@ -7,7 +7,10 @@ | |||
- [feature] Added `clearPersistence()`, which clears the persistent storage | |||
including pending writes and cached documents. This is intended to help | |||
write reliable tests (https://github.com/firebase/firebase-js-sdk/issues/449). | |||
|
|||
- [changed] Instead of failing silently, Firestore now crahses the client app |
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.
Typo: crahses -> crashes
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.
Fixed. Thanks :)
firebase-firestore/CHANGELOG.md
Outdated
SSL Ciphers during a connection attempt. | ||
- [changed] Instead of failing silently, Firestore now crahses the client app | ||
if it fails to load SSL Ciphers. To avoid these crashes, you must bundle | ||
Conscrupt if you support non-GMSCore devices on Android KitKat or JellyBean |
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.
Another typo: Conscrypt. :)
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.
This was already fixed: 080792b
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.
It also might make sense to create an integ test for this, not sure how feasible it will be to implement, but you have that option as you can request that the test runs on an old device, e.g. here's how you can control what device(s) tests run on:
device 'model=walleye,version=28' // Pixel2 | |
device 'model=walleye,version=27' // Pixel2 | |
device 'model=victara,version=19' // Moto X | |
device 'model=Nexus4,version=22' | |
device 'model=Nexus7,version=21' | |
device 'model=Nexus4,version=19' | |
device 'model=starqlteue,version=26' // Galaxy S9 | |
device 'model=m0,version=18' // Galaxy S3 | |
device 'model=hero2lte,version=23' // Galaxy S7 | |
device 'model=htc_m8,version=19' // HTC One (M8) |
@@ -211,4 +213,13 @@ public static String toDebugString(ByteString bytes) { | |||
public static String typeName(@Nullable Object obj) { | |||
return obj == null ? "null" : obj.getClass().getName(); | |||
} | |||
|
|||
/** Raises an exception on Android's UI Thread and crashes the end user's app. */ | |||
public static void crashMainThread(RuntimeException exception) { |
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.
Minor nit: the exception's stacktrace is constructed when the exception is created, not when it is thrown. So the throw site(below) will not be part of the resulting stacktrace, make sure it is ok and won't cause confusion as I am not familiar enough with your codebase to make such a call.
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.
The Stacktrace reflects the callsite for this function, which is either AbstractStream or FirestoreChannel. To me, those are the correct places and I prefer this over crashing from Util.
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.
sgtm
I am going to merge this without Integration tests. I have verified it manually and a "council of elders" has determined that the benefit of having an Integration tests that verifies that we are crashing does not outweigh its cost. (*) Still looking for members. |
We should hard-fail the Firestore client if we are running on an old Android device with no SSL ciphers.
I manually verified that this works with the WatchStream, the WriteStream and Transactions. Stacktrace looks as follows: