This is the current, and hopefully final, strategy: ## New IPDL Protocols ### `PRemoteWorkerController` The Remote Worker infrastructure operates over `PBackground`, with the parent-process-side endpoint being `RemoteWorkerController` and the child-process-side endpoint being `RemoteWorkerChild`. To integrate `ServiceWorkerPrivate` into this system, it needs to access a `RemoteWorkerController`. This will happen over the `PRemoteWorkerController` protocol, which connects the main thread and background thread in the parent process. ### `PFetchEventOp` `PFetchEventOp` is a `PBackground`-managed protocol that connects the main thread and background thread in the parent process. A `PFetchEventOp` actor represents an in-progress Fetch event. i.e., the lifetime of a `FetchEventOpChild` corresponds to the lifetime of a `FetchEvent` (more or less). `FetchEventOpChild` will keep a reference to a `KeepAliveToken` as well as an `nsIInterceptedChannel` and can manipulate the intercepted channel on behalf of the content process. `FetchEventOpChild` should be able to synthesize a response from an `InternalResponse`, avoiding the need to use the channel abstraction. On the other hand, `FetchEventOpParent` creates `PFetchEventOpProxy` actors (see below). ### `PFetchEventOpProxy` Commands/queries/operations from the content process can’t directly access the parent-process main thread due to the Remote Worker infrastructure existing exclusively over `PBackground`, so `PFetchEventOpProxy` acts as a proxy for the `PFetchEventOp` protocol. `FetchEventOpParent` will own a `FetchEventOpProxyParent`. ### `ServiceWorkerOpArgs` (not a protocol, but still IPC related) `ServiceWorkerOpArgs` is an IPDL union of all possible service worker “operations” (e.g. `ServiceWorkerFetchEventOpArgs`, `ServiceWorkerMessageEventOpArgs`, etc.). Everything necessary to construct a service worker event/runnable is packaged into a struct and sent through the various protocols and to the content process as a `ServiceWorkerOpArgs` union. `RemoteWorkerChild` will ultimately determine what specific operation is received and handle is accordingly. ### `ServiceWorkerOpResult` `ServiceWorkerOpResult` is similar to `ServiceWorkerOpArgs`; it’s used to communicate the result of an operation (and any necessary callback arguments) across IPC. ## Determining when an operation is complete For those operations that only have one dispatch/response cycle (which is looking like everything but Fetch), the lifetime of the operation corresponds to the lifetime of the `MozPromise` returned by `PRemoteWorkerControllerChild::SendExecServiceWorkerOp` (called by `ServiceWorkerPrivate`). This promise is then resolved or rejected by the `MozPromise` returned by `PRemoteWorkerParent::SendExecServiceWorkerOp` (called by `RemoteWorkerController`). For Fetch, this is determined by the `FetchEventOp(Proxy)` actors’ lifetimes rather than a `MozPromises`’ lifetimes, in a similar fashion. ## Summary Service worker operations are encapsulated by a `ServiceWorkerOpArgs` object that can be sent across IPC. The path of a `ServiceWorkerOpArgs` object is `ServiceWorkerPrivate` -> `RemoteWorkerControllerChild` -> `RemoteWorkerControllerParent` -> `RemoteWorkerController` -> `RemoteWorkerParent` -> `RemoteWorkerChild` -> `WorkerPrivate`. There are many objects to pass through due to this whole process happening over 3 threads. When a non-fetch operation completes in the content process, the steps for telling the parent process that the operation has completed is as follow: 1) Create a `ServiceWorkerOpResult` that’s used to call a `PRemoteWorkerChild::ExecServiceWorkerOpResolver` 2) That call will then resolve the promise returned from `PRemoteWorkerParent::SendExecServiceWorkerOp`, whose resolution then calls `PRemoteWorkerControllerParent::ExecServiceWorkerOpResolver` 3) That call them will resolve the promise returned from `PRemoteWorkerControllerChild::SendExecServiceWorkerOp`, where callbacks, if any, can then be called. 4) The operation is complete, and its associated `KeepAliveToken` is destroyed. Steps for a Fetch operation are similar but use `FetchEventOp(Proxy)` actor destruction rather than `MozPromise` resolution/rejection.
Bug 1231213 Comment 6 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
This is the current, and hopefully final, strategy: ## New IPDL Protocols ### `PRemoteWorkerController` The Remote Worker infrastructure operates over `PBackground`, with the parent-process-side endpoint being `RemoteWorkerController` and the child-process-side endpoint being `RemoteWorkerChild`. To integrate `ServiceWorkerPrivate` into this system, it needs to access a `RemoteWorkerController`. This will happen over the `PRemoteWorkerController` protocol, which connects the main thread and background thread in the parent process. ### `PFetchEventOp` `PFetchEventOp` is a `PBackground`-managed protocol. A `PFetchEventOp` actor represents an in-progress Fetch event. i.e., the lifetime of an actor corresponds to the lifetime of a `FetchEvent` (more or less). There will be two pairs of actors implementing PFetchEventOp{Parent,Child}; one to link the main/background threads in the main process, and one to link the background thread in the main process to the Worker Launcher thread in the content process (where RemoteWorkerChild lives). Commands/queries/operations from the content process can’t directly access the parent-process main thread due to the Remote Worker infrastructure existing exclusively over `PBackground`, so the second pair of actors is needed to act as a proxy for the first pair of actors. The child actor from the first pair will keep a reference to a `KeepAliveToken` as well as an `nsIInterceptedChannel` and can manipulate the intercepted channel on behalf of the content process. It should be able to synthesize a response from an `InternalResponse`, avoiding the need to use the channel abstraction. ### `PFetchEventOpProxy` ### `ServiceWorkerOpArgs` (not a protocol, but still IPC related) `ServiceWorkerOpArgs` is an IPDL union of all possible service worker “operations” (e.g. `ServiceWorkerFetchEventOpArgs`, `ServiceWorkerMessageEventOpArgs`, etc.). Everything necessary to construct a service worker event/runnable is packaged into a struct and sent through the various protocols and to the content process as a `ServiceWorkerOpArgs` union. `RemoteWorkerChild` will ultimately determine what specific operation is received and handle is accordingly. ### `ServiceWorkerOpResult` `ServiceWorkerOpResult` is similar to `ServiceWorkerOpArgs`; it’s used to communicate the result of an operation (and any necessary callback arguments) across IPC. ## Determining when an operation is complete For those operations that only have one dispatch/response cycle (which is looking like everything but Fetch), the lifetime of the operation corresponds to the lifetime of the `MozPromise` returned by `PRemoteWorkerControllerChild::SendExecServiceWorkerOp` (called by `ServiceWorkerPrivate`). This promise is then resolved or rejected by the `MozPromise` returned by `PRemoteWorkerParent::SendExecServiceWorkerOp` (called by `RemoteWorkerController`). For Fetch, this is determined by the `FetchEventOp` actors’ lifetimes rather than a `MozPromises`’ lifetimes, in a similar fashion. ## Summary Service worker operations are encapsulated by a `ServiceWorkerOpArgs` object that can be sent across IPC. The path of a `ServiceWorkerOpArgs` object is `ServiceWorkerPrivate` -> `RemoteWorkerControllerChild` -> `RemoteWorkerControllerParent` -> `RemoteWorkerController` -> `RemoteWorkerParent` -> `RemoteWorkerChild` -> `WorkerPrivate`. There are many objects to pass through due to this whole process happening over 3 threads. When a non-fetch operation completes in the content process, the steps for telling the parent process that the operation has completed is as follow: 1) Create a `ServiceWorkerOpResult` that’s used to call a `PRemoteWorkerChild::ExecServiceWorkerOpResolver` 2) That call will then resolve the promise returned from `PRemoteWorkerParent::SendExecServiceWorkerOp`, whose resolution then calls `PRemoteWorkerControllerParent::ExecServiceWorkerOpResolver` 3) That call them will resolve the promise returned from `PRemoteWorkerControllerChild::SendExecServiceWorkerOp`, where callbacks, if any, can then be called. 4) The operation is complete, and its associated `KeepAliveToken` is destroyed. Steps for a Fetch operation are similar but use `FetchEventOp` actor destruction rather than `MozPromise` resolution/rejection.
This is the current, and hopefully final, strategy: ## New IPDL Protocols ### `PRemoteWorkerController` The Remote Worker infrastructure operates over `PBackground`, with the parent-process-side endpoint being `RemoteWorkerController` and the child-process-side endpoint being `RemoteWorkerChild`. To integrate `ServiceWorkerPrivate` into this system, it needs to access a `RemoteWorkerController`. This will happen over the `PRemoteWorkerController` protocol, which connects the main thread and background thread in the parent process. ### `PFetchEventOp` `PFetchEventOp` is a `PBackground`-managed protocol. A `PFetchEventOp` actor represents an in-progress Fetch event. i.e., the lifetime of an actor corresponds to the lifetime of a `FetchEvent` (more or less). There will be two pairs of actors implementing PFetchEventOp{Parent,Child}; one to link the main/background threads in the main process, and one to link the background thread in the main process to the Worker Launcher thread in the content process (where RemoteWorkerChild lives). Commands/queries/operations from the content process can’t directly access the parent-process main thread due to the Remote Worker infrastructure existing exclusively over `PBackground`, so the second pair of actors is needed to act as a proxy for the first pair of actors. The child actor from the first pair will keep a reference to a `KeepAliveToken` as well as an `nsIInterceptedChannel` and can manipulate the intercepted channel on behalf of the content process. It should be able to synthesize a response from an `InternalResponse`, avoiding the need to use the channel abstraction. ### `ServiceWorkerOpArgs` (not a protocol, but still IPC related) `ServiceWorkerOpArgs` is an IPDL union of all possible service worker “operations” (e.g. `ServiceWorkerFetchEventOpArgs`, `ServiceWorkerMessageEventOpArgs`, etc.). Everything necessary to construct a service worker event/runnable is packaged into a struct and sent through the various protocols and to the content process as a `ServiceWorkerOpArgs` union. `RemoteWorkerChild` will ultimately determine what specific operation is received and handle is accordingly. ### `ServiceWorkerOpResult` `ServiceWorkerOpResult` is similar to `ServiceWorkerOpArgs`; it’s used to communicate the result of an operation (and any necessary callback arguments) across IPC. ## Determining when an operation is complete For those operations that only have one dispatch/response cycle (which is looking like everything but Fetch), the lifetime of the operation corresponds to the lifetime of the `MozPromise` returned by `PRemoteWorkerControllerChild::SendExecServiceWorkerOp` (called by `ServiceWorkerPrivate`). This promise is then resolved or rejected by the `MozPromise` returned by `PRemoteWorkerParent::SendExecServiceWorkerOp` (called by `RemoteWorkerController`). For Fetch, this is determined by the `FetchEventOp` actors’ lifetimes rather than a `MozPromises`’ lifetimes, in a similar fashion. ## Summary Service worker operations are encapsulated by a `ServiceWorkerOpArgs` object that can be sent across IPC. The path of a `ServiceWorkerOpArgs` object is `ServiceWorkerPrivate` -> `RemoteWorkerControllerChild` -> `RemoteWorkerControllerParent` -> `RemoteWorkerController` -> `RemoteWorkerParent` -> `RemoteWorkerChild` -> `WorkerPrivate`. There are many objects to pass through due to this whole process happening over 3 threads. When a non-fetch operation completes in the content process, the steps for telling the parent process that the operation has completed is as follow: 1) Create a `ServiceWorkerOpResult` that’s used to call a `PRemoteWorkerChild::ExecServiceWorkerOpResolver` 2) That call will then resolve the promise returned from `PRemoteWorkerParent::SendExecServiceWorkerOp`, whose resolution then calls `PRemoteWorkerControllerParent::ExecServiceWorkerOpResolver` 3) That call them will resolve the promise returned from `PRemoteWorkerControllerChild::SendExecServiceWorkerOp`, where callbacks, if any, can then be called. 4) The operation is complete, and its associated `KeepAliveToken` is destroyed. Steps for a Fetch operation are similar but use `FetchEventOp` actor destruction rather than `MozPromise` resolution/rejection.