Bug 1263887 - [e10s] The dropdown selector is not working properly.
Let’s try to see what’s happening here.

Hypothesis: The <option> list is changing AFTER the popup has opened. Non-e10s has the ability to react to such mutations, whereas e10s does not.

Test: Attach a mutation listener to the <select> and have it dump. Have SelectContentHelper dump when it’s sending the list to the parent. See if the one comes after the other.


Results:

CORRECT!

So I think we want to hear about mutations, and then update the parent with updates.

This appears to work, but there’s a complication - we can’t just clear out the menupopup and repopulate it, because when a frame is destroyed within a menupopup, something is queued that removes the _moz-menuactive attribute from the menuitem which removes the selection highlighting, which looks bad.

Ah, okay, I think I’ve found a workaround.

If I call:

menulist.menuBoxObject.activeChild = item;

Just after I select the selected item, then the nsMenuActivateEvent will fire (again).

AAAAND backed out. Here’s the issue:

14:54:33     INFO -  101 INFO Entering test bound
14:54:33     INFO -  102 INFO TEST-PASS | browser/base/content/test/plugins/browser_CTP_crashreporting.js | Plugin should not be activated -
14:54:33     INFO -  103 INFO TEST-UNEXPECTED-FAIL | browser/base/content/test/plugins/browser_CTP_crashreporting.js | uncaught exception - TypeError: this.menuBoxObject is undefined at set_selectedItem@chrome://global/content/bindings/menulist.xml:257:13
14:54:33     INFO -  set_value@chrome://global/content/bindings/menulist.xml:111:15
14:54:33     INFO -  plugin-popupnotification-center-item_XBL_Constructor@chrome://browser/content/urlbarBindings.xml:1856:9
14:54:33     INFO -  PopupNotifications_showPanel/promise<@resource://gre/modules/PopupNotifications.jsm:747:1
14:54:33     INFO -  Handler.prototype.process@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:937:23
14:54:33     INFO -  this.PromiseWalker.walkerLoop@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:816:7
14:54:33     INFO -  Promise*this.PromiseWalker.scheduleWalkerLoop@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:747:11
14:54:33     INFO -  this.PromiseWalker.schedulePromise@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:779:7
14:54:33     INFO -  this.PromiseWalker.completePromise@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:714:7
14:54:33     INFO -  receiveMessage@resource://testing-common/ContentTask.jsm:113:9
14:54:33     INFO -  Stack trace:
14:54:33     INFO -  chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:simpletestOnerror:1563
14:54:33     INFO -  resource://gre/modules/PopupNotifications.jsm:PopupNotifications_showPanel/promise<:747
14:54:33     INFO -  resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:Handler.prototype.process:937
14:54:33     INFO -  resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:this.PromiseWalker.walkerLoop:816
14:54:33     INFO -  JavaScript error: chrome://global/content/bindings/menulist.xml, line 257: TypeError: this.menuBoxObject is undefined
14:54:33     INFO -  104 INFO Console message: [JavaScript Error: "TypeError: this.menuBoxObject is undefined" {file: "chrome://global/content/bindings/menulist.xml" line: 257}]
14:54:33     INFO -  set_selectedItem@chrome://global/content/bindings/menulist.xml:257:13
14:54:33     INFO -  set_value@chrome://global/content/bindings/menulist.xml:111:15
14:54:33     INFO -  plugin-popupnotification-center-item_XBL_Constructor@chrome://browser/content/urlbarBindings.xml:1856:9
14:54:33     INFO -  PopupNotifications_showPanel/promise<@resource://gre/modules/PopupNotifications.jsm:747:1
14:54:33     INFO -  Handler.prototype.process@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:937:23
14:54:33     INFO -  this.PromiseWalker.walkerLoop@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:816:7
14:54:33     INFO -  Promise*this.PromiseWalker.scheduleWalkerLoop@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:747:11
14:54:33     INFO -  this.PromiseWalker.schedulePromise@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:779:7
14:54:33     INFO -  this.PromiseWalker.completePromise@resource://gre/modules/Promise.jsm -> resource://gre/modules/Promise-backend.js:714:7
14:54:33     INFO -  receiveMessage@resource://testing-common/ContentTask.jsm:113:9
14:54:33     INFO -  Xlib:  extension "RANDR" missing on display ":0".

FUCK. Fuck fuck fuck. The menulist.xml change I made is causing this test failure:

26 INFO TEST-UNEXPECTED-FAIL | chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul | addItemToSelection(1): getSelectedChildren: wrong selected children count for ['menupopup node', address: [object XULElement], role: combobox list, name: 'item2', address: [xpconnect wrapped (nsISupports, nsIAccessible, nsIAccessibleSelectable)]] - got +0, expected 1
SimpleTest.is@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:268:5
testSelectableSelection@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable.js:19:3
doTest/<@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul:47:9
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
doTest@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul:46:7
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
addA11yLoadEvent/waitForDocLoad/<@chrome://mochitests/content/a11y/accessible/tests/mochitest/common.js:169:9
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
waitForDocLoad@chrome://mochitests/content/a11y/accessible/tests/mochitest/common.js:159:5
SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:741:59

27 INFO TEST-UNEXPECTED-FAIL | chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul | Can't get accessible for  'cb1_item2'
getAccessible@chrome://mochitests/content/a11y/accessible/tests/mochitest/common.js:276:9
testSelectableSelection@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable.js:24:23
doTest/<@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul:47:9
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
doTest@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul:46:7
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
addA11yLoadEvent/waitForDocLoad/<@chrome://mochitests/content/a11y/accessible/tests/mochitest/common.js:169:9
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
waitForDocLoad@chrome://mochitests/content/a11y/accessible/tests/mochitest/common.js:159:5
SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:741:59
28 INFO TEST-UNEXPECTED-FAIL | chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul | uncaught exception - TypeError: selectedChildren is null at testSelectableSelection@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable.js:25:9
doTest/<@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul:47:9
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
doTest@chrome://mochitests/content/a11y/accessible/tests/mochitest/selectable/test_menulist.xul:46:7
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
addA11yLoadEvent/waitForDocLoad/<@chrome://mochitests/content/a11y/accessible/tests/mochitest/common.js:169:9
setTimeout handler*SimpleTest_setTimeoutShim@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:622:12
waitForDocLoad@chrome://mochitests/content/a11y/accessible/tests/mochitest/common.js:159:5
SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:741:59

For some reason, I can’t get at the “accessible” here. Why? WHY WHY WHY WHY???

And strangely, it seems like if I just attempt to get at the activeChild (I don’t even need to set it)

GAH

* thread #1: tid = 0xa3cf6a, 0x000000010833e158 XUL`mozilla::a11y::DocAccessible::BindToDocument(this=0x0000000121cd3bc0, aAccessible=0x0000000121c9dd00, aRoleMapEntry=0x0000000000000000) + 24 at DocAccessible.cpp:1255, queue = 'com.apple.main-thread', stop reason = breakpoint 6.1
frame #0: 0x000000010833e158 XUL`mozilla::a11y::DocAccessible::BindToDocument(this=0x0000000121cd3bc0, aAccessible=0x0000000121c9dd00, aRoleMapEntry=0x0000000000000000) + 24 at DocAccessible.cpp:1255
frame #1: 0x000000010830cb0e XUL`nsAccessibilityService::CreateAccessible(this=0x00000001240b6460, aNode=0x000000012648ab80, aContext=0x00000001267ac780, aIsSubtreeHidden=0x00007fff5fbfb2af) + 5214 at nsAccessibilityService.cpp:1284
frame #2: 0x000000010830b278 XUL`mozilla::a11y::TreeWalker::AccessibleFor(this=0x00007fff5fbfb418, aNode=0x000000012648ab80, aFlags=0, aSkipSubtree=0x00007fff5fbfb2af) + 264 at TreeWalker.cpp:295
frame #3: 0x000000010830af7e XUL`mozilla::a11y::TreeWalker::Next(this=0x00007fff5fbfb418, aStopNode=0x000000012648adc0) + 494 at TreeWalker.cpp:148
frame #4: 0x000000010833f657 XUL`InsertIterator::Next(this=0x00007fff5fbfb408) + 663 at DocAccessible.cpp:1731
* frame #5: 0x000000010833f741 XUL`mozilla::a11y::DocAccessible::ProcessContentInserted(this=0x0000000121cd3bc0, aContainer=0x00000001267ac780, aNodes=0x0000000128732f88) + 161 at DocAccessible.cpp:1756
frame #6: 0x00000001082f4ea1 XUL`mozilla::a11y::NotificationController::WillRefresh(this=0x0000000123e1d800, aTime=(mValue = 993637834003943)) + 817 at NotificationController.cpp:233
frame #7: 0x000000010793c391 XUL`nsRefreshDriver::Tick(this=0x0000000128343800, aNowEpoch=1461598038664384, aNowTime=(mValue = 993637834003943)) + 1217 at nsRefreshDriver.cpp:1698
frame #8: 0x0000000107942af8 XUL`mozilla::RefreshDriverTimer::TickDriver(driver=0x0000000128343800, jsnow=1461598038664384, now=(mValue = 993637834003943)) + 136 at nsRefreshDriver.cpp:274
frame #9: 0x00000001079429ba XUL`mozilla::RefreshDriverTimer::TickRefreshDrivers(this=0x000000012c74d560, aJsNow=1461598038664384, aNow=(mValue = 993637834003943), aDrivers=0x000000012c74d580) + 186 at nsRefreshDriver.cpp:246
frame #10: 0x0000000107942859 XUL`mozilla::RefreshDriverTimer::Tick(this=0x000000012c74d560, jsnow=1461598038664384, now=(mValue = 993637834003943)) + 249 at nsRefreshDriver.cpp:264
frame #11: 0x000000010794484d XUL`mozilla::VsyncRefreshDriverTimer::RunRefreshDrivers(this=0x000000012c74d560, aTimeStamp=(mValue = 993637834003943)) + 125 at nsRefreshDriver.cpp:588
frame #12: 0x0000000107943dd9 XUL`mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::TickRefreshDriver(this=0x000000012c6c4b80, aVsyncTimestamp=(mValue = 993637834003943)) + 361 at nsRefreshDriver.cpp:508
frame #13: 0x0000000107944424 XUL`decltype(o=0x000000012c6c4b80, m=0x0000000107943c70, args=0x0000000123a205f0, (null)=IndexSequence<0> @ 0x00007fff5fbfc5b8).*fp0(mozilla::Get<0ul>(fp1).PassAsParameter())) nsRunnableMethodArguments<mozilla::TimeStamp>::applyImpl<mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver, void (mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::*)(mozilla::TimeStamp), StoreCopyPassByValue<mozilla::TimeStamp>, 0ul>(mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver*, void (mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::*)(mozilla::TimeStamp), mozilla::Tuple<StoreCopyPassByValue<mozilla::TimeStamp> >&, mozilla::IndexSequence<0ul>) + 164 at nsThreadUtils.h:671
frame #14: 0x0000000107944359 XUL`_ZN25nsRunnableMethodArgumentsIJN7mozilla9TimeStampEEE5applyINS0_23VsyncRefreshDriverTimer26RefreshDriverVsyncObserverEMS5_FvS1_EEEDTcl9applyImplfp_fp0_dtdefpT10mArgumentscvNS0_13IndexSequenceIJLm0EEEE_EEEPT_T0_(this=0x0000000123a205f0, o=0x000000012c6c4b80, m=0x0000000107943c70) + 73 at nsThreadUtils.h:677
frame #15: 0x0000000107943ff6 XUL`nsRunnableMethodImpl<void (mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::*)(mozilla::TimeStamp), true, mozilla::TimeStamp>::Run(this=0x0000000123a205c0) + 134 at nsThreadUtils.h:705
frame #16: 0x000000010321f391 XUL`nsThread::ProcessNextEvent(this=0x0000000102921100, aMayWait=false, aResult=0x00007fff5fbfc883) + 2001 at nsThread.cpp:994
frame #17: 0x00000001032a6a37 XUL`NS_ProcessPendingEvents(aThread=0x0000000102921100, aTimeout=10) + 151 at nsThreadUtils.cpp:232
frame #18: 0x00000001074f2936 XUL`nsBaseAppShell::NativeEventCallback(this=0x000000011ed22f70) + 198 at nsBaseAppShell.cpp:97
frame #19: 0x000000010758c235 XUL`nsAppShell::ProcessGeckoEvents(aInfo=0x000000011ed22f70) + 501 at nsAppShell.mm:387
frame #20: 0x00007fff8f96ca01 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #21: 0x00007fff8f95eb8d CoreFoundation`__CFRunLoopDoSources0 + 269
frame #22: 0x00007fff8f95e1bf CoreFoundation`__CFRunLoopRun + 927
frame #23: 0x00007fff8f95dbd8 CoreFoundation`CFRunLoopRunSpecific + 296
frame #24: 0x00007fff87b5c56f HIToolbox`RunCurrentEventLoopInMode + 235
frame #25: 0x00007fff87b5c1ee HIToolbox`ReceiveNextEventCommon + 179
frame #26: 0x00007fff87b5c12b HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 71
frame #27: 0x00007fff91a798ab AppKit`_DPSNextEvent + 978
frame #28: 0x00007fff91a78e58 AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 346
frame #29: 0x000000010758acf7 XUL`-[GeckoNSApplication nextEventMatchingMask:untilDate:inMode:dequeue:](self=0x0000000102939e90, _cmd="nextEventMatchingMask:untilDate:inMode:dequeue:", mask=18446744073709551615, expiration=4001-01-01 00:00:00 UTC, mode=@"kCFRunLoopDefaultMode", flag=YES) + 119 at nsAppShell.mm:121
frame #30: 0x00007fff91a6eaf3 AppKit`-[NSApplication run] + 594
frame #31: 0x000000010758cc1c XUL`nsAppShell::Run(this=0x000000011ed22f70) + 172 at nsAppShell.mm:661
frame #32: 0x000000010873c0e1 XUL`nsAppStartup::Run(this=0x0000000121a51380) + 161 at nsAppStartup.cpp:284
frame #33: 0x00000001087f4a0e XUL`XREMain::XRE_mainRun(this=0x00007fff5fbfe880) + 6206 at nsAppRunner.cpp:4347
frame #34: 0x00000001087f5936 XUL`XREMain::XRE_main(this=0x00007fff5fbfe880, argc=5, argv=0x00007fff5fbff1a8, aAppData=0x00007fff5fbfeb08) + 1414 at nsAppRunner.cpp:4451
frame #35: 0x00000001087f5e27 XUL`::XRE_main(argc=5, argv=0x00007fff5fbff1a8, aAppData=0x00007fff5fbfeb08, aFlags=0) + 103 at nsAppRunner.cpp:4559
frame #36: 0x0000000100002851 firefox`do_main(argc=5, argv=0x00007fff5fbff1a8, envp=0x00007fff5fbff1d8, xreDirectory=0x0000000102913340) + 2017 at nsBrowserApp.cpp:220
frame #37: 0x0000000100001b8e firefox`main(argc=5, argv=0x00007fff5fbff1a8, envp=0x00007fff5fbff1d8) + 302 at nsBrowserApp.cpp:360
frame #38: 0x0000000100001604 firefox`start + 52

So it looks like there’s some kind of deferred “binding” or something in DocAccessible::BindToDocument that makes the menuitem that’s in the menulist expose its accessibility interface… and that’s occurring _after_ the test has finished, on the next tick of the refresh driver, it looks like.

Looks like this is doing it: https://hg.mozilla.org/mozilla-central/file/10f66b316457/layout/xul/BoxObject.cpp#l120

The FlushPendingNotifications seems to… I dunno, unbind things?