Closed Bug 903441 (ServiceWorkers) Opened 11 years ago Closed 1 year ago

[meta] Implement Service Workers


(Core :: DOM: Service Workers, task, P2)






(Reporter: ehsan.akhgari, Unassigned)


(Depends on 7 open bugs, Blocks 1 open bug, )


(Keywords: dev-doc-needed, meta, Whiteboard: [games:p1][platform-rel-Games])


(26 obsolete files)

      No description provided.
Is there a spec somewhere? Or is it an internal thing?
Its an experimental API right now. Updated URL to relevant discussion, but everything else is hand-wavy.
OS: Mac OS X → All
Hardware: x86 → All
Attached patch Patch 1: rebased-sharedworkers (obsolete) — Splinter Review
A cleaned up patch bent sent me that is required before applying the event page/service patch.
Attached patch Patch 2: Service (obsolete) — Splinter Review
This is a first pass of Services that doesn't do a lot, but might be useful to Ehsan to figure out Navigation Controller and also a good time to layout my thoughts about further implementation.

What this code does do right now:
Inherits SharedWorker, to expose a Service() constructor to DOM (we could call it EventPage I guess, depending on how it gets used). This starts a (shared )worker, with the addition of a `mIsService` flag. A service is *not* immediately killed when all referring windows are closed. In fact, right now its lifetime is completely isolated from referring windows (which is not how it should be!). When it's event loop Dispatch() receives no events for some time (right now 13 seconds for no real reason), it cancels the service.

The rest of the discussion is in dev.platform (will paste link here).
Attachment #789292 - Flags: feedback?(mounir)
Attachment #789292 - Flags: feedback?(jonas)
Attachment #789292 - Flags: feedback?(ehsan)
Comment on attachment 789292 [details] [diff] [review]
Patch 2: Service

Jonas and Ehsan's feedbacks should be enough.
Attachment #789292 - Flags: feedback?(mounir)
Comment on attachment 789292 [details] [diff] [review]
Patch 2: Service

Review of attachment 789292 [details] [diff] [review]:

Feedback on the concept level issues given on the dev.webapi thread.

::: dom/workers/RuntimeService.cpp
@@ +2091,5 @@
> +    }
> +
> +    if (!windowArray->Contains(workerPrivate)) {
> +      windowArray->AppendElement(workerPrivate);
> +    }

Can this be refactored into a helper method?

::: dom/workers/RuntimeService.h
@@ +155,5 @@
> +  nsresult
> +  CreateBackgroundService(JSContext* aCx, nsPIDOMWindow* aWindow,
> +                          const nsAString& aScriptURL, const nsAString& aName,
> +                          Service** aSharedWorker);

Nit: please prefer returning an already_AddRefed<Service> if possible.

::: dom/workers/Service.cpp
@@ +20,5 @@
> +} // anonymous namespace
> +
> +Service::Service(nsPIDOMWindow* aWindow,
> +                           WorkerPrivate* aWorkerPrivate)
> +: SharedWorker(aWindow, aWorkerPrivate)

Not sure if you're looking for whitespace nits quite yet.  ;-)

@@ +27,5 @@
> +}
> +
> +Service::~Service()
> +{
> +  AssertIsOnMainThread();

It's not immediately clear to me what guarantees this...

::: dom/workers/SharedWorker.h
@@ +47,5 @@
>    nsRefPtr<MessagePort> mMessagePort;
> +
> +  /**
> +   * Used to dispatch a Resume() event back to the SharedWorker itself.
> +   * XXXnsm I'm not sure why this has to be done using a Runnable.

Perhaps because we want to keep the object alive until the desired method is called on it?

@@ -80,5 @@
>    virtual nsresult
>    PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
> -private:

Nit: please make these protected.

::: dom/workers/Worker.cpp
@@ +105,5 @@
>    static JSObject*
>    Construct(JSContext* aCx, WorkerPrivate* aParentObj,
>              const nsAString& aScriptURL, bool aIsChromeWorker,
> +            const nsAString& aSharedWorkerName, bool aIsService);

Nit: an enum would probably make the call sites more readable than a bool.

::: modules/libpref/src/init/all.js
@@ +89,5 @@
>  // Whether or not Shared Web Workers are enabled.
>  pref("dom.workers.sharedWorkers.enabled", true);
> +// Whether or not Background Service Workers are enabled.
> +pref("dom.workers.service.enabled", true);

This should obviously default to false when you get to land this...
Attachment #789292 - Flags: feedback?(ehsan) → feedback+
Comment on attachment 789292 [details] [diff] [review]
Patch 2: Service

Review of attachment 789292 [details] [diff] [review]:

Nikhil, sadly I won't have time to go over this very soon. Especially as I'm heading out for vacation for a week and then it's the B2G workweek. Feel free to poke me after that if you want my feedback on the code. But I'd prefer to just go over the API instead.
Attachment #789292 - Flags: feedback?(jonas) → feedback?
Attached patch Service Worker proof of concept (obsolete) — Splinter Review
This is a much simplified patch over the earlier 'ugliness'. It:

* Does not present a DOM facing constructor or access to these workers.
* Does not require Shared Workers patches
* Almost entirely avoids modifying any existing worker code.
* Adds a single interface nsIServiceWorkerManager with a SendEvent() method that always creates a new Worker and sends the event to it. The plan is to make this do caching and stuff and integrate it with existing worker infrastructure.

If you have the time, can you fiddle with integrating this into Necko in some tiny sense? intercepting a http request and feeding it to this as an event. SendEvent() does not currently accept data, just an event name.
Attachment #789277 - Attachment is obsolete: true
Attachment #789292 - Attachment is obsolete: true
Attachment #789292 - Flags: feedback?
Flags: needinfo?(ehsan)
Alarm API with certain security checks disabled that enables it on web pages on Firefox Desktop, and uses nsIServiceWorkerManager rather than system messages.
Forgot to point out that the patch hard codes the Service Worker being at http://localhost:8000. Change the paths when you compile. Patches to fix this will come later.

Small test page which served from |python -m SimpleHTTPServer| will work with the localhost:8000 thing.
Nikhil, Josh is now working on NavController.  Josh, please see comment 8.  Thanks!
Flags: needinfo?(ehsan) → needinfo?(josh)
Summary: Implement Event Pages → Implement Service Workers
Attached patch ServiceWorkerManager (obsolete) — Splinter Review
Creates a window-less Worker.

RegisterServiceWorker() will load the URL and send it an install event.

SendEvent() can be used to send events. This will spawn a new Worker for every event, which is not what we want if the previous worker is alive (which it is since this does not terminate service workers yet).
Attachment #801003 - Attachment is obsolete: true
Useful for doing service worker specific stuff like introducing Cache APIs.

Josh, could you write a small WebIDL wrapper around your work in the Navigation Controller bug to create a simple Cache or SameOriginResponse and introduce it into the worker scope of a Service Worker?
Attached patch Promises on Workers. (obsolete) — Splinter Review
Assignee: nsm.nikhil → josh
This is still missing some glue to create a FetchEvent, since we need to pass it a channel. In theory calling respondWith and passing a SameOriginResponse would do the right thing, however.
Marked Promises on worker bug as blocking this. That patch may be updated on bug 915233.

I have a WIP patch that adds InstallPhaseEvent and InstallEvent and some changes to existing patches.Since ServiceWorkers introduces these new events that may be dispatched on the Worker global, we need to wait for the conversion of WorkerPrivate and WorkerScope to use the main thread EventTarget infrastructure rather than implement custom events on the current code. khuey has a WIP patch for this, but he is on pseudo-vacation.
Depends on: 915233
Comment on attachment 814940 [details] [diff] [review]
Promises on Workers.

Obsoleting this patch as it does not make Promises 'usable' (runnable dispatch) on workers, while patch in referenced bug does.refer
Attachment #814940 - Attachment is obsolete: true
Blocks: 922363
(In reply to Nikhil Marathe [:nsm] from comment #17)
> … we need to wait for the conversion of WorkerPrivate and WorkerScope to
> use the main thread EventTarget infrastructure rather than implement 
> custom events on the current code. khuey has a WIP patch for this, but
> he is on pseudo-vacation.

Can you add the bug to the dependency list then, please?
Ah sorry, I misunderstood your comment. I just saw that Bug 915233 depends on Bug 914762 which you probably meant in Comment 18, right?
(In reply to Florian Bender from comment #20)
> Ah sorry, I misunderstood your comment. I just saw that Bug 915233 depends
> on Bug 914762 which you probably meant in Comment 18, right?

I did mean 915233 in comment 18. As for Kyle's patch, I don't know the bug number.
Unfinished, since the whole bit about actually creating and dispatching the FetchEvent is unclear to me. However, this should theoretically intercept document navigations for documents with active service workers.
Flags: needinfo?(josh)
I stole this by accident.
Assignee: josh → nsm.nikhil
Josh, ' Add Response, Request, SameOriginResponse, and FetchEvent implementations.' is missing FetchEvent.cpp. Could you update the patch? Thanks!
Flags: needinfo?(josh)
(please use Gecko coding style in content/ and dom/* code)
Attachment #814942 - Attachment is obsolete: true
Assignee: nsm.nikhil → josh
More interception, along with deducing fetch type and top level-ness.
Assignee: josh → nsm.nikhil
Flags: needinfo?(josh)
Hanging off tasks off this as I think of them.
Summary: Implement Service Workers → [meta] Implement Service Workers
Integrates into the SharedWorker infrastructure (needs more work) and dispatches the "install" event. Will be split into more bugs soon.
Unbitrot, add support for querying domain info about service worker.
Comment on attachment 830923 [details] [diff] [review]
Intercept images, fonts, objects, stylesheets, and XHRs.

Review of attachment 830923 [details] [diff] [review]:

::: image/src/imgLoader.cpp
@@ +434,5 @@
>                       aPolicy);
>    if (NS_FAILED(rv))
>      return rv;
> +  newChannel = aLoadingDocument->InterceptFetch(newChannel, nsIDocument::Fetch);

This needs a null check.
Added hashtables to keep track of ServiceWorkers.
Various Runnables to pass requests to and from workers.
Mark a document as being controlled in StartDocumentLoad.
Comment on attachment 8343448 [details] [diff] [review]
Make document navigation cause a ServiceWorker fetch event.

Review of attachment 8343448 [details] [diff] [review]:

::: content/base/src/nsDocument.cpp
@@ +2474,5 @@
>    }
> +  bool dummy;
> +  nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
> +  swm->StartInterception(this, &dummy);

How do we plan to make use of the success value in the future?

::: dom/interfaces/base/nsIServiceWorkerManager.idl
@@ +17,5 @@
> +  void sendFetchEvent(in nsIDocument aDocument, in nsIAlternateSourceChannel aChannel, in nsIURI aPageURI);
> +  bool isControlled(in nsIDocument aDocument);
> +  // Returns a ServiceWorker or null.
> +  nsISupports GetServiceWorker(in nsIDocument aDocument);
> +  bool startInterception(in nsIDocument aDocument);

The return value needs documentation.

::: dom/workers/ServiceWorkerManager.cpp
@@ +355,5 @@
> +    JS::Rooted<JSObject*> jsGlobal(aCx, target->GetWrapper());
> +    GlobalObject globalObject(aCx, jsGlobal);
> +
> +    mozilla::dom::RequestInit init;
> +    init.mUrl.Construct(NS_ConvertUTF8toUTF16(mResourceURL));

I'm not convinced that using this URL across threads is safe. I would be inclined to store the spec and create a new URL here.

@@ +468,5 @@
> +  return NS_OK;
> +}
> +
> +static nsresult
> +GetDocumentDomain(nsIDocument* aDoc, nsCString& domain, JSContext* cx = nullptr)

This method feels like it should reside elsewhere (like in document code), but that's just my gut feeling.

@@ +520,5 @@
> +ServiceWorkerManager::IsControlled(nsIDocument* aDoc, bool* aControlled)
> +{
> +  MOZ_ASSERT(NS_IsMainThread());
> +  nsCString domain;
> +  nsresult rv = GetDocumentDomain(aDoc, domain);

rv is ignored

@@ +560,5 @@
> +ServiceWorkerManager::StartInterception(nsIDocument* aDoc, bool* aSuccess)
> +{
> +  MOZ_ASSERT(NS_IsMainThread());
> +  nsCString domain;
> +  nsresult rv = GetDocumentDomain(aDoc, domain);

rv is ignored.

@@ +821,5 @@
> +    return NS_OK;
> +  }
> +
> +  nsCString domain;
> +  nsresult rv = aDocument->GetDocumentURI()->GetHost(domain);

rv is ignored
Various rebases, spec updates and minor things to make these usable.
Depends on: 1032521
Depends on: 1038973
Depends on: 1045257
Depends on: 1047398
Depends on: 1053483
Depends on: 1056702
Depends on: 1065216
Depends on: 1065515
Depends on: 1065367
Depends on: 1065366
Depends on: 1078808
Depends on: 1080109
Depends on: 1080110
Whiteboard: [dependency: marketplace-partners]
Depends on: 1109680
jdm, are any of the attachments here relevant any longer? Otherwise I'll obsolete all of them.
Flags: needinfo?(josh)
Wow. No.
Flags: needinfo?(josh)
Assignee: nsm.nikhil → nobody
Depends on: 1194562
See Also: → 1227104
Whiteboard: [dependency: marketplace-partners] → [dependency: marketplace-partners][games:p1]
Whiteboard: [dependency: marketplace-partners][games:p1] → [dependency: marketplace-partners][games:p1][platform-rel-Games]
platform-rel: --- → ?
No longer depends on: ServiceWorkers-B2G
No longer blocks: sw-devtools
Whiteboard: [dependency: marketplace-partners][games:p1][platform-rel-Games] → [games:p1][platform-rel-Games]
I've attempted to clean up this bug to use as a meta for ongoing service worker efforts.  I've hung some child meta bugs for different efforts underneath it:

  Bug 1226983 (ServiceWorkers-compat): Spec compatibility issues
  Bug 1262699 (ServiceWorkers-devtools): Make it easier for web devs to build service workers
  Bug 1328391 (ServiceWorkers-data): Add telemetry to support data driven development
  Bug 1328622 (ServiceWorkers-perf): Performance testing and optimizations
  Bug 1328614 (ServiceWorkers-tests): Issues with service worker related tests
  Bug 1283191 (ServiceWorkers-streams): Integrate WHATWG streams API into service workers
  Bug 1212882 (ServiceWorkers-foreign): Implement foreign fetch
I also added:

  Bug 1328631 (ServiceWorkers-stability): To track crashes, assertions, or other stability issues
platform-rel: ? → ---
Priority: -- → P2
Component: DOM → DOM: Core & HTML
Type: defect → task

The task is meanwhile 6 years in progress and service workers are not enabled in the esr release versions per default.
When can you expect them enabled per default?

I've filed bug 1547023 to track enabling ServiceWorkers in ESR. I think there's a discussion still to be had there, but my presumption right now is that they would not be enabled on ESR 68. If you're aware of any ESR installations that would benefit from ServiceWorkers support and why the installations can't use non-ESR Firefox, I believe that would be useful information that would inform the decision-making process.

Depends on: ServiceWorkers-ESR
Component: DOM: Core & HTML → DOM: Service Workers

:asuth What is the purpose of this meta bug (it seems we have implemented Service Workers, after all)? And we have a component to link all relevant bugs to, too. I'd prefer then smaller meta bugs for concrete, spec-related enhancements rather than this unspecific thing.

Flags: needinfo?(bugmail)

I think it started out as a meta bug for the initial implementation and now is just a meta bug of meta bugs providing connective linkage between the various meta-bugs and providing some level of discoverability via traversal (versus search). I'm not sure it provides much value, we can probably resolve this WORKSFORME.

Flags: needinfo?(bugmail)
Severity: normal → S3

Resolving this per above comments.

Closed: 1 year ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.