| Overview of chrome://sync-internals |
| ----------------------------------- |
| |
| This note explains how chrome://sync-internals (also known as |
| about:sync) interacts with the sync service/backend. |
| |
| Basically, chrome://sync-internals sends asynchronous messages to the |
| sync backend and the sync backend asynchronously raises events to |
| chrome://sync-internals, either when replying to messages or when |
| something interesting happens. |
| |
| Both messages and events have a name and a list of arguments, the |
| latter of which is represented by a JsArgList (js_arg_list.h) object, |
| which is basically a wrapper around an immutable ListValue. |
| |
| TODO(akalin): Move all the js_* files into a js/ subdirectory. |
| |
| Message/event flow |
| ------------------ |
| |
| chrome://sync-internals is represented by SyncInternalsUI |
| (chrome/browser/web_ui/sync_internals_ui.h). SyncInternalsUI |
| interacts with the sync service via a JsFrontend (js_frontend.h) |
| object, which has a ProcessMessage() method. The JsFrontend can |
| handle some messages itself, but it can also delegate the rest to a |
| JsBackend instance (js_backend.h), which also has a ProcessMessage() |
| method. A JsBackend can in turn handle some messages itself and |
| delegate to other JsBackend instances. |
| |
| Essentially, there is a tree with a JsFrontend as the root and |
| JsBackend as non-root internal nodes and leaf nodes (although |
| currently, the tree is more like a simple list). The sets of messages |
| handled by the JsBackends and the JsFrontend are disjoint, which means |
| that at most one node handles a given message type. Also, the |
| JsBackends may live on different threads, but JsArgList is thread-safe |
| so that's okay. |
| |
| SyncInternalsUI is a JsEventHandler (js_event_handler.h), which means |
| that it has a HandleJsEvent() method, but JsBackends cannot easily |
| access those objects. Instead, each JsBackend keeps track of its |
| parent router, which is a JsEventRouter object (js_event_router.h). |
| Basically, a JsEventRouter is another JsBackend object or a JsFrontend |
| object. So an event travels up through the JsEventRouter until it |
| reaches the JsFrontend, which knows about the existing JsEventHandlers |
| (via AddHandler()/RemoveHandler()) and so can delegate to the right |
| one. |
| |
| A diagram of the flow of a message and its reply: |
| |
| msg(args) -> F -> B -> B -> B |
| | | | |
| H <- R <- R <- R <- reply-event(args) |
| |
| F = JsFrontend, B = JsBackend, R = JsEventRouter, H = JsEventHandler |
| |
| Non-reply events are percolated up similarly. |