-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix(reviewers): support localStorage again #18369
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
|
The unit tests fail with error, for example, "ReviewerNoParamTest > differentDeckPenColorDoesNotAffectCurrentDeck FAILED It seems related to your code and not a flake, so I won't review tonight |
|
Issue with macos (or the macos emulator). Unfornutately, I don't have a mac, so I can't help with that. |
@BrayanDSO Seems fixed by the following, be sure to move the line out from Index: AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt (revision 2a095f64b82de977e3eecdf36d77683e7b8a93da)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt (date 1748911426702)
@@ -664,6 +664,7 @@
override fun onDestroy() {
super.onDestroy()
+ server.stop()
tts.releaseTts(this)
// WebView.destroy() should be called after the end of use
// http://developer.android.com/reference/android/webkit/WebView.html#destroy() |
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.
(might be worthwhile moving this to one of the two issues)
For now, the port randomization offers some form of defence against access to the backend. We lose this 'obscurity' if we hardcode the port
Due to this, I'd be tempted to put it behind an advanced/developer option until the above issue is resolved.
Don't want to be a nag here, but it's security.
In addition: I don't believe the 'find another port' logic was working correctly on macOS; could this be explicitly tested on Android
|
I don't have the time nor the expertise to audit every detail and I'm quite in favor of making it a dev option for now |
|
Maybe it is worth to randomize the port once, save the result in a |
|
Sure, that works for me, thanks! |
342cdcf to
cd68eec
Compare
|
Okay, now the port is "private" and under a developer option. It can be promoted to an |
david-allison
left a comment
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 concern that I believe getServerPort would not use 0 on macOS if the port is in use
❗Could do with a comment
❗Add a Timber on BindException so developers know a nonstandard port is used
Minor concern that we haven't defined "what happens to developer options if we disable the preference"
But that's out of scope and should be moved to a separate issue
Code is great, looks good to me
After the migration to use a server that can handle the backend POST requests, AnkiDroid moved from having a static base URL to a dynamic one because the server port could change. This fixes the issue by using a default port number. That should work in 99% of the cases. If by chance another app uses the same port, a free one will be used instead. I haven't tested, but this may happen with parallel builds of AnkiDroid running at the same time. Still, the only issue that would surge is that localStorage wouldn't work on one of open builds until the other one is closed
1. Put the fixed port under an opt-in developer option due to uncertainty about the security until someone takes a deeper look in the matter 2. Randomize the initial value of the port so the port isn't publicly known
mikehardy
left a comment
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 like it - and I think it's fine as a developer setting now though I think even putting it as an advanced / non-developer setting now would be fine since it defaults to randomization and you have to opt-in to any possible extra security risk
one wording change (everyone proposes a wording change...) but it is intended to explain the setting which hopefully makes the idea more discoverable and the setting more useful
+1 though, approval stands regardless
| android:summary="Touch here to set the database path to /storage/emulated/0/AnkiDroid" | ||
| android:key="@string/pref_set_database_path_debug_key"/> | ||
| <SwitchPreferenceCompat | ||
| android:title="Use fixed port in the Reviewer" |
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.
a couple more words with intention to de-mystify the setting a bit, what do you think?
| android:title="Use fixed port in the Reviewer" | |
| android:title="Use fixed port to enable javascript localStorage in Reviewer" |
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 comment was marked as resolved.
This comment was marked as resolved.
so regular users can use it
| <string name="readtext_reviewer_warn" tools:ignore="UnusedResources">Please upgrade to the new text to speech format</string> | ||
| <string name="pref_fixed_port_title" maxLength="41">localStorage in Study Screen</string> | ||
| <string name="pref_fixed_port_summary" | ||
| >Enables JavaScript localStorage by using a fixed server port in the Study Screen</string> |
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.
Our translators aren't gonna like this one
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 agree. Completely open to simplify it, but I found hard doing that without losing context enough to explain the setting.
Honestly, I tend to prefer just making it the default. Even if you get access to the port,
- CORS is rejected by default
- All GET requests to the server are rejected
Method.GET -> { Timber.d("Rejecting GET request to server %s", session.uri) newFixedLengthResponse(Response.Status.NOT_FOUND, null, null) } else -> { Timber.d("Ignored request of unhandled method %s, uri %s", session.method, session.uri) newFixedLengthResponse(null) - The POST requests are somewhat restricted (idk about the JS API)
override suspend fun handlePostRequest(
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'll remove this from the merge queue if you're also unhappy. This was NOT a blocking comment, so feel free to re-add it. No 'hard' advice on this one, but I'd prefer it as a developer-only setting. We can expect developers to read.
I found hard doing that without losing context enough to explain the setting.
Good reason for a developer-only setting.
CORS is rejected by default
CORS is client-side security. A malicious app would skip the OPTIONS call.
Honestly, I tend to prefer just making it the default.
Hard no until we resolve
Especially with how this is currently in the tech news cycle: https://www.zeropartydata.es/p/localhost-tracking-explained-it-could
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's an advanced setting and under the Workarounds category. I think it matches any possible expectatives from the public. Some advanced notetypes from shared decks may use it, and I don't want people going to Developer options just to enable it.
Since I'm no expert in security, and it's way harder and time consuming to defend than to attack, I'll merge it as an Advanced setting.
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 think this is a good compromise - advanced ppl will really want this, but it is opt in so don't increase surface area by default
|
Shoot. Should have synced strings |
I had just synced them - there just can't have been much in there, no problem with this one |

After the migration to use a server that can handle the backend POST requests, AnkiDroid moved from having a static base URL to a dynamic one because the server port could change.
This fixes the issue by using a default port number. That should work in 99% of the cases.
If by chance another app uses the same port, a free one will be used instead. I haven't tested, but this may happen with parallel builds of AnkiDroid running at the same time. Still, the only issue that would surge is that localStorage wouldn't work on one of open builds until the other one is closed
Fixes
Approach
In the commits
How Has This Been Tested?
Emulator 35 by using JS's localStorage between app sessions
Learning (optional, can help others)
I also tried to use a placeholder static URL, like
https://foo.bar, then redirect the request to the server. That actually worked, but it was buggy and too hacky.Checklist
Please, go through these checks before submitting the PR.