Firefox exposes removal operations for IndexedDB databases, object
stores, and records from the Storage panel. Route those actor requests
to LibWeb so DevTools can delete the selected data and receive the
update or clear event needed to refresh the panel.
The Storage panel expects storesUpdate messages after watched storage
changes. Summarize committed IndexedDB mutation logs into DevTools paths
and forward them through WebContent so Firefox can refresh database,
object-store, and record rows without polling.
Firefox's behaviour is less than ideal here. A lot of things don't
update automatically even inspecting a page in Firefox. Some
things (like new databases) won't show up until you fully refresh the
page. So that makes it a bit hard to know that we're doing things
correctly. As far as I can tell, we are at least behaving as well as
Firefox requires.
We do have one workaround: Firefox doesn't display record updates
without a manual refresh, and in fact any change messages for them show
up as rows in the host's database table. So for now, we filter them out
to avoid visual weirdness in the inspector.
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 sends the same storage actor mutation requests for Web Storage
that it uses for cookies. Handle addItem, editItem, removeItem, and
removeAll for localStorage and sessionStorage actors.
Apply the changes through the browser-process storage jar and emit the
matching store update packets so the Storage panel stays current after a
DevTools-initiated edit.
Firefox keeps the Storage panel current by sending store update packets
when localStorage or sessionStorage changes. Forward successful Web
Storage mutations to the storage actors and emit the matching update or
clear packet.
Use listener IDs for storage updates so the local and session storage
actors can subscribe independently.
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.
DevTools needs to edit and delete cookies from the browser process. Add
a small mutation surface to CookieJar and expose it through the DevTools
delegate while preserving the existing cookie notification path.
Firefox keeps the Storage table current through storesUpdate messages
from the storage actor. Forward browser cookie change notifications to
the cookies actor and classify visible rows against a fresh cookie
snapshot.
The existing cookie-change notifications report cookies that are
relevant to a specific page, whereas DevTools wants all cookies
relevant for a host, so we end up having to provide two different sets
of cookies to `notify_cookies_changed()`.
Firefox asks the cookies actor for rows after selecting a Storage host.
Read the browser cookie jar through the DevTools delegate and serialize
matching cookies with the fields Firefox expects.
This keeps mutation support disabled, but makes existing cookies visible
in the Storage panel.
Extend the existing DOM node inspection request with an options payload
and carry it through the browser process, WebView, IPC, and WebContent.
This lets later DevTools requests forward Firefox's top-level flags
without changing any inspected-node behavior yet.
Firefox's remote toolbox exposes an editable URL field for tab
descriptors. Submitting that field sends navigateTo to the tab
descriptor rather than the frame target.
Handle the request in the tab actor, route it through the DevTools
delegate, and reuse WebView's URL sanitizing and load path. Add protocol
coverage so the toolbar navigation request stays wired up.
Firefox's inspector toolbar sends goBack and goForward requests to the
tab descriptor when the descriptor advertises navigation support. Thread
those requests through the DevTools delegate and reuse the existing
WebView session-history traversal path.
Keep the legacy frame-target requests working too, matching Firefox's
window-global target compatibility surface. Add protocol coverage for
both entry points so the advertised trait and deltas stay locked down.
Firefox reloads remote targets through the tab descriptor's
reloadDescriptor request. We advertised support for that request, but
left it unhandled, so Firefox could clear inspector state without
causing Ladybird to reload the page.
Route reloadDescriptor, and the legacy frame target reload request,
through the DevTools delegate to WebView's reload path. This lets the
existing navigation notifications publish the replacement inspector root
after the reload completes.
Firefox starts element picking by sending pick to the walker actor. Add
matching protocol handling so Ladybird can enter picker mode, send
hover, preview, pick, and cancel events, and serialize picked nodes in
the shape Firefox expects.
Picker hit testing can return text nodes, but Firefox only selects
elements in this mode. Normalize picker events to the closest element
ancestor and include the parent chain so Firefox can materialize missing
tree nodes before selecting the target.
Add IPC structures and requests for inspecting grid layout data from
WebContent.
WebView forwards the async replies to LibDevTools and exposes the grid
highlighter hooks used by the protocol layer.
Parse Firefox grid highlighter options in WebContent and store them with
the active grid highlight.
To avoid unnecessary IPC traffic, we now only send network response
bodies when a DevTools client is connected.
This requires tracking DevTools connection state in ViewImplementation
so we can propagate it to new WebContent processes created during
cross-site navigation.
Propagate the request initiator type (e.g., "xmlhttprequest", "fetch",
"script", "stylesheet") from LibWeb through the IPC layer to DevTools.
This enables Firefox DevTools to correctly identify XHR/fetch requests
and display appropriate cause types in the Network panel's "Initiator"
column.
This adds support for viewing request payloads (POST data) and response
bodies in the Firefox DevTools network panel.
Request bodies are captured when network requests start and passed
through IPC to the NetworkEventActor, which returns them via the
getRequestPostData protocol method.
Response bodies are streamed via a new IPC message as data is received,
accumulated in NetworkEventActor (with a 10MB size limit to prevent
memory issues), and returned via getResponseContent. Text content is
returned as UTF-8, while binary content (images, etc.) is base64.
Previously, console messages were sent using an index-based system where
DevTools would be notified of new message indices and then request them
in batches. This created synchronization issues during page navigation
when the WebContent process resets while DevTools still has stale index
state.
This changes to a push-based model where console messages are sent
immediately as resources when they are logged, matching how Firefox
DevTools handles console messages. Each message is pushed through IPC
and forwarded to DevTools as a "console-message" or "error-message"
resource.
This eliminates the need for index tracking in FrameActor and simplifies
the entire console message pipeline from WebContent through to DevTools.
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>
The upcoming generated types will match those for pseudo-classes: A
PseudoElementSelector type, that then holds a PseudoElement enum
defining what it is. That enum will be at the top level in the Web::CSS
namespace.
In order to keep the diffs clearer, this commit renames and moves the
types, and then a following one will replace the handwritten enum with
a generated one.
When we inspect a DOM node, we currently serialize many properties for
that node, including its layout, computed style, used fonts, etc. Now
that we aren't piggy-backing on the Inspector interface, we can instead
only serialize the specific information required by DevTools.
These commands are used for the "Edit As HTML" feature in DevTools. This
renames our existing HTML getter IPC to indicate that it is for outer
HTML. DevTools will need a separate inner HTML getter.
This requires a couple of amendments to the DOM node serialization.
Namely, we need to include the HTML namespace, otherwise the context
menu item to create a new node is disabled.
LibDevTools was implicitly including generated IPC endpoints from
LibWebView. This is not a dependency declared in the CMakeLists.txt. So
updates to the IPC file might not have caused the endpoint header to be
regenerated by the time LibDevTools is compiled, resulting in a build
error.
This patch removes that implicit dependency entirely.
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.
Previously, we could connect to our DevTools server from Firefox, but
could not see any information on Ladybird's opened tabs. This implements
enough of the protocol to see a tab list, but we cannot yet inspect the
tabs.
To aid with debugging web page issues in Ladybird without needing to
implement a fully fledged inspector, we can implement the Firefox
DevTools protocol and use their DevTools. The protocol is described
here:
https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html
This commit contains just enough to connect to Ladybird from a DevTools
client.