The view's synchronous per-result data -- a dynamic result's view template and
a result's menu commands -- was fetched from the result's provider on demand,
which the message path can't do when the provider lives in another process. It
worked around this by pre-fetching the data with each QueryResults notification
and stashing it on a non-enumerable `viewData` expando that the view read back.
Compute it eagerly instead, when the result is finalized in
UrlbarProvidersManager, and store it on UrlbarResult as `viewTemplate` and
`commands`. Both are serialized by toWire()/fromWire(), so the view reads them
synchronously on both transports without a round-trip or the expando (and its
deepEqual/serialization hazard). getViewUpdate stays dynamic and round-trips.
Static per-result data a provider parked in getViewUpdate moves to the baked
template too: RealtimeSuggestProvider set the result's navigation url/query on
the row's dataset from getViewUpdate, so on the message path a click resolved no
URL until that async update landed. Baking the dataset into getViewTemplate makes
it present when the row is built; only genuinely dynamic per-item data (text,
images, aria group) stays in getViewUpdate.
Because the commands are baked, a provider that changes them while the result
stays in the view must refresh the baked value, not just drop the view's command
cache -- reaching the "show less frequently" cap removes that command, and the
stale baked commands would otherwise keep it. Consolidate the show-less-frequently
handling each suggestion provider inlined into a shared
SuggestProvider.handleShowLessFrequently that re-bakes the result's commands, so
the refresh lives in one place rather than being repeated (and missable) per
provider.
Differential Revision: https://phabricator.services.mozilla.com/D310082