SpellCheckCustomDictionary — Android WebView
What is being tested. The per-document dictionary lives in the renderer
(SpellCheckProvider::document_custom_words_) and filters results
after they come back from the platform checker, so on Android it should
behave the same as on desktop even though the misspellings themselves are
found by Android, not by Hunspell. These steps check that the filtering, the
per-document scoping, and the caps all survive that round trip.
1. WebView opt-in: only spellcheck="true" is checked
Tap into each field below (Android checks text through the platform
checker; a field may not be checked until it is focused).
1a. Opted in. Contains wugzz .
This wugzz is misspelled.
1b. Control, no attribute. Same word, no
spellcheck attribute.
This wugzz is misspelled.
Tap into 1a: wugzz should get a red squiggle.
Tap into 1b: it should get no squiggle. WebView sets
spellcheck_enabled_by_default = false, so an app's existing
content is never spell checked unless it opts in.
If 1a shows no squiggle either, stop: the emulator has no working spell
checker service (the setup doc, step 2) and no later test is meaningful.
2. addWords() suppresses the squiggle document-wide
Both regions contain flooble : one
contenteditable, one <textarea>, since
WebView apps use both.
A flooble in a contenteditable.
addWords(["flooble"])
Tap into each region and confirm flooble is
squiggled in both .
Tap addWords once. The squiggle should clear in both
regions, without any further interaction — one call covers the
whole document, not just the focused field.
3. removeWords() restores the squiggle
Field contains grimpy .
One grimpy word here
addWords(["grimpy"])
removeWords(["grimpy"])
Tap into the field, confirm grimpy is
squiggled, then tap addWords — the squiggle clears.
Tap removeWords . If the field still has focus the squiggle comes
back on the spot; if focus moved away, tap back into the field. Either
way it must return without typing : removal clears
SpellCheckProvider's cached result and invalidates the
per-document check state, and a fresh pass then runs when the editable
is focused by a user gesture. Unlike desktop, the answer arrives from
another app in the emulator, so give it a second or two before calling
it a failure.
If it still has not returned, type one character and delete it, and
record whether it returns then. That distinction matters: coming back
only after an edit would mean the focus-driven refresh is not reaching
the platform checker on Android, even though it does on desktop. Note
which of the two steps made the squiggle reappear.
4. Matching is verbatim, and independent of script
Matching is exact: the stored word must equal the checked word.
A brilligzzz and a Brilligzzz.
addWords(["brilligzzz"])
4b is optional and only observable if the emulator's
spell checker language (the setup doc, step 2) is set to a language that flags the
text below. With an English-only spell checker service, Hebrew text is
never flagged and there is nothing to see; record 4b as N/A in that case.
זה שלוס לא נכון.
addWords(["שלוס"])
Tap into 4a. Check whether both brilligzzz and
Brilligzzz are squiggled. If the platform
checker leaves the capitalised form alone (some treat a capitalised
word as a proper noun), the case part of this test is not observable on
this image — record it as N/A and skip to Test 5. Gboard on
google_apis does flag it, so it is normally observable.
Tap addWords(["brilligzzz"]) . The lower-case one clears; the
capitalised one stays squiggled. The filter is an exact string
match on the misspelled word
(SpellCheck::CreateTextCheckingResults), so it is verbatim,
not case-folded.
(Optional) Repeat for 4b with the RTL word.
5. The dictionary is per-document, and does not survive a load
The set is cleared in SpellCheckProvider::DidCreateNewDocument().
A WebView is typically reused for many page loads, so a word added by one
page must not leak into the next.
The word snorpled again.
addWords(["snorpled"])
Reload this page
Tap into the field, confirm snorpled is
squiggled, then tap addWords — the squiggle clears.
Tap Reload this page , come back to this field and tap into it.
snorpled must be squiggled again : the
new document starts with an empty dictionary.
Reloading also resets Tests 1–4, so run this before Test 6 and
redo any earlier step you still need.
6. Per-document caps (20000 words / 128 bytes per word)
Run this last. The bulk step fills the per-document set for the rest
of this document's life, so every earlier addWords would be
silently dropped afterwards. If you need the earlier tests again, reload
first.
Field A contains zzzzzqqqqq , field B contains
capwordzz .
zzzzzqqqqq is misspelled.
capwordzz is misspelled.
A: addWords(["zzzzzqqqqq"])
Fill cap: addWords(21000 words + 1 over-long word)
B: addWords(["capwordzz"])
Below the cap. Tap into field A, then tap
A: addWords . Its squiggle clears — normal behaviour below
the cap.
Fill the cap. Tap Fill cap . WebView must not crash or ANR,
the page must stay scrollable and responsive, and the DevTools console
(the setup doc, step 6) should show exactly one warning:
“per-document word limit reached…” . The
warning is emitted once per document, so tapping Fill cap again
must not add a second one.
Above the cap. Tap into field B, then tap B: addWords . The
squiggle on capwordzz must stay : the
word is rejected because the set is full. If it clears, the cap is not
being enforced.
Results
Copy results