Firefox asks the storage watcher for an indexed-db resource before it
shows IndexedDB entries in the Storage panel. Add an IndexedDB actor and
serialize the live LibWeb database registry on demand, so WebContent can
return the host tree and table rows without duplicating database state.
Use the LibWeb inspection helpers to read IndexedDB internals, and keep
the Firefox protocol shape in LibDevTools. WebContent only forwards the
serialized response over the existing DevTools IPC path.
Firefox exposes localStorage and sessionStorage through the same
storage actor protocol used by cookies. Add matching resources for the
current tab so the Storage panel can list key/value pairs.
Read the values through WebContent rather than directly from the
browser process. Session storage lives in LibWeb, and using the same
path for both stores keeps the actor independent of the backing store.
Firefox discovers Storage panel data through watcher resources. This
adds a read-only cookies actor with the fields and empty store response
expected by the Storage panel.
Mutation traits are reported as unsupported for now.
DevTools storage resources all have a "host" key derived from the URL,
which we produce in `storage_host_for_url()`.
Resolve applied-rule stylesheet identities through StyleSheetsActor and
include Firefox parentStyleSheet, line, and column fields on rule forms.
Firefox can then show matched rules as stylesheet rules and open the
corresponding CSS source location from the Rules panel.
Firefox keeps using the same walker after navigation and expects it to
publish the new document root.
Normal tab debugging also relies on target switching. Re-inspect the tab
when navigation finishes, replace the walker DOM data, and notify the
watcher that the previous top-level frame target was destroyed before a
fresh target becomes available.
Send target availability as a watcher event, not as the watchTargets
response, and give each navigation a new inner window id so Firefox can
associate the new target with the new document.
When a page navigates, send document-event resources with
"will-navigate" and tabNavigated messages so Firefox DevTools
can follow along and clear the Network panel appropriately.
Hook ResourceLoader to emit network request lifecycle events through
IPC to the UI process, where FrameActor creates NetworkEventActor
instances that serialize requests using Firefox's Remote Debug Protocol.
The Network panel now shows requests with method, URL, status, MIME
type, size, and timing information. Several features remain stubbed
(POST data, response content, cause detection) marked with FIXMEs.
This is enough for Firefox to display the Accessibility tab, containing
our accessibility tree which can be inspected. Most information is
blank for now.
There's quite a bit of duplication between AccessibilityWalkerActor and
WalkerActor - it might be worth trying to make a base class once the
details are figured out. Frustratingly, the two don't work quite the
same: for a lot of messages that would be sent to WalkerActor, the
accessibility equivalent is sent to the AccessibilityNodeActor instead.
Co-authored-by: Tim Flynn <trflynn89@pm.me>
We must reply to requests received from the client in the order they are
received. The wrench in this requirement is handling requests that must
be performed asynchronously, such as fetching the serialized DOM tree
from the WebContent process.
We currently handle this with a "block token". Async request handlers
hold a token that blocks any subsequent responses from being sent. When
that token is removed (i.e. the async request now has a response to be
sent), the async response is then sent followed by the blocked responses
in-order.
This strategy had a limitation that we could not handle an actor trying
to take 2 block tokens, meaning only one async request could be handled
at a time. This has been fine so far, but an upcoming feature (style
sheet sources) will break this limitation. The client will request N
sources at a time, which would try to take N block tokens.
The new strategy is to assign all requests an ID, and store a list of
request IDs that are awaiting a response. When the server wants to send
a reply, we match the ID of the replied-to message to this list of IDs.
If it is not the first in this list, then we are blocked waiting for an
earlier reply, and just store the response. When the earlier request(s)
receive their response, we can then send out all blocked replies (up to
the next request that has not yet received a response).
This is to prepare for an upcoming change where we will need to track
replies to messages by ID. We will be able to add parameters to this
structure without having to edit every single actor subclass header
file.
This is just to help make the message handlers a bit briefer. I had
considered adding a TRY-like macro to auto-return when the lookup fails,
but since statement expressions cannot return references, that would
result in a copy of all e.g. object and array lookups.
The "from" field is required in every response. It is the name of the
actor sending the message. This patch fills in the "from" field in the
Actor base class so that subclasses don't have to.
There is a lot needed all at once to actually inspect a tab's DOM tree.
It begins with requesting a "watcher" from a TabActor. It seems there
can be many types of watchers, but here we implement the "frame" watcher
only. The watcher creates an "inspector", which in turn creates a
"walker", which is the actor ultimately responsible for serializing and
inspecting the DOM tree.
In between all that, the DevTools client will send a handful of other
informational requests. If we do not reply to these, the client will not
move forward with the walker. For example, the CSSPropertiesActor will
be asked for a list of all known CSS properties.