Closed Bug 1140105 Opened 10 years ago Closed 10 years ago

Can't query for a specific font face when the selection is collapsed

Categories

(Core :: DOM: Editor, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla40
Tracking Status
firefox40 --- fixed

People

(Reporter: neil, Assigned: jorgk-bmo)

References

Details

Attachments

(1 file, 9 obsolete files)

When there is a selection, nsHTMLEditor::GetInlineProperty passes the desired font face through to IsCSSEquivalentToHTMLInlineStyleSet, but when the selection is collapsed, it fails to do so. This can be observed in Thunderbird by opening the Format Font submenu. 1. Format - Font - Times and type "Times". 2. Format - Font - Courier and type "Courier". 3. Select the "u" of "Courier" and notice that the Format - Font submenu displays the correct font. 4. Collapse the selection and notice that the Format - Font submenu display is incorrect.
Note that it's not possible to query a specific font from the typing state at all. This appears to be a long-standing bug, so I will address that separately.
Attached patch Proposed patch (obsolete) (deleted) — Splinter Review
Assignee: nobody → neil
Status: NEW → ASSIGNED
Attachment #8573493 - Flags: review?(ehsan)
Comment on attachment 8573493 [details] [diff] [review] Proposed patch Review of attachment 8573493 [details] [diff] [review]: ----------------------------------------------------------------- Please add a test for this.
Attachment #8573493 - Flags: review?(ehsan) → review+
(In reply to Ehsan Akhgari from comment #3) > Please add a test for this.
I hate bugzilla's tabbing order.
(In reply to neil@parkwaycc.co.uk from comment #6) > https://hg.mozilla.org/integration/mozilla-inbound/rev/4b7febba9c14 (with > test) Again, I don't think we run anything from editor/libeditor/TextEditorTest.cpp. Also, what's up with the xpcom/string/nsTStringObsolete.cpp changes? I think you want to put that in a separate patch and get it reviewed.
(In reply to Ehsan Akhgari from comment #8) > (In reply to comment #6) > > https://hg.mozilla.org/integration/mozilla-inbound/rev/4b7febba9c14 (with > > test) > > Again, I don't think we run anything from > editor/libeditor/TextEditorTest.cpp. Well, I was able to run that test locally, but it's the only other caller of that function, so it's not as if there's any more obvious way of testing it. > Also, what's up with the xpcom/string/nsTStringObsolete.cpp changes? I > think you want to put that in a separate patch and get it reviewed. Whoops, I hadn't realised that my tree wasn't clean. Sorry about that.
Blocks: 1142879
(In reply to neil@parkwaycc.co.uk from comment #9) > (In reply to Ehsan Akhgari from comment #8) > > (In reply to comment #6) > > > https://hg.mozilla.org/integration/mozilla-inbound/rev/4b7febba9c14 (with > > > test) > > > > Again, I don't think we run anything from > > editor/libeditor/TextEditorTest.cpp. > > Well, I was able to run that test locally, but it's the only other caller of > that function, so it's not as if there's any more obvious way of testing it. How did you run the test? AFAICT this is only triggered from <http://mxr.mozilla.org/mozilla-central/source/editor/libeditor/nsHTMLEditor.cpp#3361> which is a dead method in nsIHTMLEditor which nothing in our code base calls. :/ (Adding a test that runs that method would be nice, but I have no idea how many other things in this test will fail as soon as you enable it.)
(In reply to neil@parkwaycc.co.uk from comment #9) > Whoops, I hadn't realised that my tree wasn't clean. Sorry about that. (In reply to :Ehsan Akhgari (not reading bugmail, needinfo? me!) from comment #10) > How did you run the test? AFAICT this is only triggered from > <http://mxr.mozilla.org/mozilla-central/source/editor/libeditor/nsHTMLEditor. > cpp#3361> which is a dead method in nsIHTMLEditor which nothing in our code > base calls. :/ Any chance to move on with this?
(In reply to Jorg K from comment #11) > Any chance to move on with this? I don't know how to write a better test for this. Maybe ehsan will accept a mozmill test?
(In reply to neil@parkwaycc.co.uk from comment #12) > (In reply to Jorg K from comment #11) > > Any chance to move on with this? > > I don't know how to write a better test for this. Maybe ehsan will accept a > mozmill test? Why would you want to have a mozmill test for this? This seems to be easily testable in a mochitest. What am I missing?
Attached patch Work around the bug in the UI code (obsolete) (deleted) — Splinter Review
Since I don't know how to write a better test, I'll work around this bug in the UI, although of course I then run into bug 1139524 too.
Attachment #8591403 - Flags: review?(iann_bugzilla)
A little sad that a one-line change in the editor for which you already have approval turns into a multiline change in the client. I was going to quiz Ehsan about how to write a test for it after my return on 23rd April. Can nsHTMLEditor::GetInlineProperty be called from a mochitest?
Flags: needinfo?(ehsan)
(In reply to Jorg K from comment #15) > A little sad that a one-line change in the editor for which you already have > approval turns into a multiline change in the client. Actually this also fixes comment #1 too, which is nice. > I was going to quiz Ehsan about how to write a test for it after my return > on 23rd April. Sorry, I had no idea you were volunteering; that's really great of you to do that. > Can nsHTMLEditor::GetInlineProperty be called from a mochitest? We do call it from Composer UI (via EditorGetTextProperty), if that helps.
Comment on attachment 8592329 [details] [diff] [review] Fix by Neil and test by Jorg K Review of attachment 8592329 [details] [diff] [review]: ----------------------------------------------------------------- Thanks a lot! ::: editor/libeditor/tests/test_bug1140105.html @@ +34,5 @@ > + is(selRange.endOffset, 9, "offset should be 9"); > + > + var firstHas = { value: false }; > + var anyHas = { value: false }; > + var allHas = { value: false }; Nit: please replace all of these by {}. The value property is automatically added to the out arguments by XPConnect. @@ +36,5 @@ > + var firstHas = { value: false }; > + var anyHas = { value: false }; > + var allHas = { value: false }; > + var editor = getEditor(); > + editor instanceof Components.interfaces.nsIHTMLEditor; Instead of this, do |editor.QueryInterface(...)|. @@ +39,5 @@ > + var editor = getEditor(); > + editor instanceof Components.interfaces.nsIHTMLEditor; > + var selcon = editor.selectionController; > + > + var gAtomService = Components.classes["@mozilla.org/atom-service;1"].getService(Components.interfaces.nsIAtomService); Please call this atomService.
Attachment #8592329 - Flags: review?(ehsan) → review+
Attachment #8592329 - Attachment is obsolete: true
Please hold off with the checkin for now. Need to investigate the M2 failures from #28 first. Also, this conflicts with bug 1154791 on one file: editor/libeditor/tests/chrome.ini (adding a new test) so the other bug needs to land first or else the patch fails.
Keywords: checkin-needed
Actually, looking at https://ftp-ssl.mozilla.org/pub/mozilla.org/firefox/try-builds/mozilla@jorgk.com-6e599d277f32/try-linux64-asan/try_ubuntu64-asan_vm_test-mochitest-2-bm51-tests1-linux64-build77.txt.gz or https://ftp-ssl.mozilla.org/pub/mozilla.org/firefox/try-builds/mozilla@jorgk.com-6e599d277f32/try-linux64/try_ubuntu64_vm_test-mochitest-2-bm114-tests1-linux64-build217.txt.gz I see: INFO - 1345 INFO TEST-UNEXPECTED-FAIL | dom/imptests/editing/conformancetest/test_runtest.html | [["inserttext","a"]] "foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz" compare innerHTML - [["inserttext","a"]] "foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz" compare innerHTML: assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<font color=\"brown\"><a href=\"http://www.google.com\">a</a></font>baz" but got "foo<font color=\"brown\"><a href=\"http://www.google.com\"><font color=\"brown\">a</font></a></font>baz" so expected: "foo<font color=\"brown\"><a href=\"http://www.google.com\">a</a></font>baz" but got: "foo<font color=\"brown\"><a href=\"http://www.google.com\"><font color=\"brown\">a</font></a></font>baz" This looks like it has something to do with the change that was made in editor/libeditor/nsHTMLEditorStyle.cpp I've got no idea what's going on here. Perhaps the test needs adjustment, hmm. If so, can you please let me know where.
You interpret the test failure like this: * [["inserttext","a"]] "foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz" --> The test was to run execCommand("inserttext", false, "a") (which is the same as typing "a") on the snippet of HTML given. Brackets indicate the position of the selection, so the word "bar" is selected. In words: what happens if you type the letter "a" when selecting the text of a colored link? * compare innerHTML --> The part that failed was the HTML output, as opposed to (for instance) the position of the selection. That is, the wrong HTML is produced. * - [["inserttext","a"]] "foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz" compare innerHTML: --> I don't know why this is repeated. * assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<font color=\"brown\"><a href=\"http://www.google.com\">a</a></font>baz" but got "foo<font color=\"brown\"><a href=\"http://www.google.com\"><font color=\"brown\">a</font></a></font>baz" -> We expected the first HTML output, but got the second. With your change, there is an extra <font color=brown> tag nested inside, which is certainly not correct: now there are two <font> tags instead of one. I don't know why the patch causes this failure, but it's a real regression and needs to be fixed before checkin. My guess is that after the word "bar" is deleted, but before "a" is inserted, something calls GetInlinePropertyBase to check the style, and for some reason expects it to be empty. You need to find this caller and fix it. Checking all the callers of GetInlinePropertyBase should identify the culprit quickly enough, there are only seven of them. Hope that helped!
Flags: needinfo?(ayg)
Assignee: neil → mozilla
Attached patch Patch, hopefully final version (obsolete) (deleted) — Splinter Review
This patch has been presented before and received r+ (comment #31). Sadly Mochitest-2 failures got overlooked (comment #28: https://treeherder.mozilla.org/#/jobs?repo=try&revision=018f3fb1f578). These failures were investigated (comment #38 to comment #60). This is the final result. There is no need to read all the comments, since a summary is contained in the code. Try run: https://treeherder.mozilla.org/#/jobs?repo=try&revision=a74537f27567 Clear apart from the usual failures ;-( Please note the following: In this bug here and in bug 1154791 new mochitests are added to editor/libeditor/tests/chrome.ini. So applying the second patch of the two might/will fail on this file. No idea who will sort this out, it's pretty obvious.
Attachment #8592656 - Attachment is obsolete: true
Attachment #8594341 - Attachment is obsolete: true
Attachment #8594435 - Flags: review?(ehsan)
Comment on attachment 8594435 [details] [diff] [review] Patch, hopefully final version Review of attachment 8594435 [details] [diff] [review]: ----------------------------------------------------------------- Before I go through all of the comments in this bug, do you know what bug exactly you're working around? And why did you choose to work around it as opposed to fix the actual bug? (BTW, it's usually a good idea to try to keep the number and length of comments in bugs small to keep them more readable. Right now for example I have a very difficult time figuring out where things are here because there are so many comments, many of which seem to just talk about debugging issues, which don't shed a light on the bigger picture. It would be a huge help if after adding these comments when they are no longer useful, you would go back and tag them as "obsolete" by clicking on the [tag] link next to each comment. That would hide them by default, which would make it easier to read the bug. Thanks!) ::: editor/libeditor/nsHTMLEditRules.cpp @@ +7586,5 @@ > + mCachedStyles[i].attr.EqualsLiteral("color")) { > + nsRefPtr<Selection> selection = mHTMLEditor->GetSelection(); > + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); > + if (selection->Collapsed()) { > + aVal = nullptr; Ouch. This hack is unfortunately unacceptable, since it's basically testing the exact condition in the test that the patch breaks, thereby just wallpapering over a real regression. The reason why having the large number of tests that we have is useful is to ensure that they catch accidental behavior changes that may be caused by seemingly unrelated changes. When we catch side behaviors, we need to fix them, not just work around the issue that the test has found like this.
Attachment #8594435 - Flags: review?(ehsan) → review-
OK, here is the executive summary: The bug is to fix nsHTMLEditor::GetInlinePropertyBase. When the selection is collapsed it doesn't pay attention to the value passed in and always returns true. If you look at the test case editor.getInlineProperty([font], "face", "Arial", firstHas, anyHas, allHas); and editor.getInlineProperty([font], "face", "Courier", firstHas, anyHas, allHas); *both* returned true. With the fix, the second returns false. This can be fixed in three lines, the: + if (aValue) { + tOutString.Assign(*aValue); + } in editor/libeditor/nsHTMLEditorStyle.cpp With this fix, all but one Mochitest work, the one that fails is this one: [["inserttext","a"]] "foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz" Expected: "foo<font color=\"brown\"><a href=\"http://www.google.com\">a</a></font>baz" but got: "foo<font color=\"brown\"><a href=\"http://www.google.com\"><font color=\"brown\">a</font></a></font>baz" In other words, the "bar" is replaced by "a" and the <font color="brown"></font> is repeated. Here is the analysis why this happens (debug): nsHTMLEditRules::CacheInlineStyles - found style via IsTextPropertySetByContent |color|brown| nsHTMLEditRules::CacheInlineStyles - found style |color|brown| nsHTMLEditRules::ReapplyCachedStyles - looking up |color|brown| nsHTMLEditor::GetInlinePropertyBase (before IsCSSEquivalentToHTMLInlineStyleSet) |color|brown| Before GetCSSEquivalentToHTMLInlineStyleSet value |brown| After GetCSSEquivalentToHTMLInlineStyleSet value |rgb(0, 0, 255)| <-- picks up true CSS color comparing (1) |rgb(165, 42, 42)| to |rgb(0, 0, 255)| nsHTMLEditor::GetInlinePropertyBase (after IsCSSEquivalentToHTMLInlineStyleSet) |color|rgb(0, 0, 255)|, result 0 nsHTMLEditRules::ReapplyCachedStyles - looked up |color|brown|, result 0 We compare the assumed color, brown, to the real colour of the element, blue. And that fails, therefore the <font color="brown"></font> is repeated. Before the fix, the no comparison took place, since the value passed in was ignored and not passed on the function that does the checking: http://mxr.mozilla.org/mozilla-central/source/editor/libeditor/nsHTMLCSSUtils.cpp#1114 The problem is that the picking up of the colour is done in "nonCSS" mode by IsTextPropertySetByContent. If CSS mode were used, this particular test would succeed but instead 66 (or 36) others would fail (depending on whether the "nonCSS" query is always used or only used for font color). Aryeh said: > I think we should always use CSS for detecting the current style, but it will probably need more > changes than just here. I don't know if it makes sense within the scope of this bug. But that's not an option here, since that produces 66 more test failures. So the options I saw were: 1) Allow on monchitest to fail (marking it as expected failure). 2) Cover up the problem as I suggested, since it leaves the same faulty behaviour in place that we've always had, only that it's not moved elsewhere and is marked with a clear comment. 3) Not fix the bug at all and work around it on the Thunderbird client. 4) Fix it for real, but so far, no one knows how. So please advise on point 4) while I obsolete all my comments made ;-)
Flags: needinfo?(ehsan)
Sorry, one more addition to understand the debug better: nsHTMLEditor::GetInlinePropertyBase calls mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet calls GetCSSEquivalentToHTMLInlineStyleSet and this picks up blue (0,0,255) which is later compared the brown (165,42,42) passed in for comparison. Of course the test returns false.
Re. comment #63: "I think we should always use CSS for detecting the current style, ..." Always using CSS to detect the properties as per https://hg.mozilla.org/try/rev/6803a356f659 gives the 66 failures listed on comment #53.
(In reply to Jorg K (at the beach until 22nd April) from comment #63) > 1) Allow one more monchitest to fail (marking it as expected failure). I've looked at all the similar tests. They are: ["foo<font color=blue><a href=http://www.google.com>[bar]</a></font>baz", [["inserttext","a"]] ["foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz", [["inserttext","a"]] ["foo<font color=blue><a href=http://www.google.com>[bar]</a></font>baz", [["delete",""],["inserttext","a"]], ["foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz", [["delete",""],["inserttext","a"]], Of these four similar tests the latter two are known failures. The first one always works, since the link colour is blue. I would have no problem whatsoever to add the second one, which is now failing, to the list of known failures and be done with this problem. Looking at more known failures in the context of color and insertion, we have these additional ones, sorry, different format: "[[\"delete\",\"\"],[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=blue>[bar]</font></a>baz\" "[[\"delete\",\"\"],[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=brown>[bar]</font></a>baz\" "[[\"delete\",\"\"],[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=black>[bar]</font></a>baz\" So it's already well and truly NON-conformant, and I'd have no qualms whatsoever to add another one (which currently works by accident!) for the sake of repairing the published interface GetInlineProperty. This function is noticeably *broken*. As stated before, the test is absolutely fictional. No user will ever be able to reproduce this problem, since the link text cannot be selected by hand, instead the whole link is selected. One day, in the fullness of time, this area can be revisited and then *all* failures can be addressed.
As explained in comment #66, I find it reasonable to allow one regression to an area which is already well and truly broken for the sake of fixing a published interface which is also well and truly broken. Enclosed the patch to do this, here a clean try run: https://treeherder.mozilla.org/#/jobs?repo=try&revision=79f0a76ed52e
Attachment #8595402 - Flags: feedback?(ehsan)
Comment on attachment 8595402 [details] [diff] [review] Patch which marks the offending test as expected failure Review of attachment 8595402 [details] [diff] [review]: ----------------------------------------------------------------- OK, since this seems to be exposing existing brokenness, it's fine to ignore this failure.
Attachment #8595402 - Flags: feedback?(ehsan) → review+
Oops, this area got reworked recently (bug 1147412), so I have to re-do my patch :-(
Flags: needinfo?(ehsan)
Keywords: checkin-needed
Carrying forward Ehsan's review+ Refreshed patch, now ready to go.
Attachment #8596806 - Attachment is obsolete: true
Attachment #8597247 - Flags: review+
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla40
Blocks: 1159923
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: