summaryrefslogtreecommitdiffstats
path: root/dom/serviceworkers/ServiceWorkerJob.h
blob: 70eed04636d90d5f20b8c9b40d333e03d3bdabbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_serviceworkerjob_h
#define mozilla_dom_serviceworkerjob_h

#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"

class nsIPrincipal;

namespace mozilla {

class ErrorResult;

namespace dom {

class ServiceWorkerJob {
 public:
  // Implement this interface to receive notification when a job completes or
  // is discarded.
  class Callback {
   public:
    // Called once when the job completes.  If the job is started, then this
    // will be called.  If a job is never executed due to browser shutdown,
    // then this method will never be called.  This method is always called
    // on the main thread asynchronously after Start() completes.
    virtual void JobFinished(ServiceWorkerJob* aJob, ErrorResult& aStatus) = 0;

    // If the job has not started and will never start, then this will be
    // called; either JobFinished or JobDiscarded will be called, but not both.
    virtual void JobDiscarded(ErrorResult& aStatus) = 0;

    NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
  };

  enum class Type { Register, Update, Unregister };

  enum class State { Initial, Started, Finished };

  Type GetType() const;

  State GetState() const;

  // Determine if the job has been canceled.  This does not change the
  // current State, but indicates that the job should progress to Finished
  // as soon as possible.
  bool Canceled() const;

  // Determine if the result callbacks have already been called.  This is
  // equivalent to the spec checked to see if the job promise has settled.
  bool ResultCallbacksInvoked() const;

  bool IsEquivalentTo(ServiceWorkerJob* aJob) const;

  // Add a callback that will be invoked when the job's result is available.
  // Some job types will invoke this before the job is actually finished.
  // If an early callback does not occur, then it will be called automatically
  // when Finish() is called.  These callbacks will be invoked while the job
  // state is Started.
  void AppendResultCallback(Callback* aCallback);

  // This takes ownership of any result callbacks associated with the given job
  // and then appends them to this job's callback list.
  void StealResultCallbacksFrom(ServiceWorkerJob* aJob);

  // Start the job.  All work will be performed asynchronously on
  // the main thread.  The Finish() method must be called exactly
  // once after this point.  A final callback must be provided.  It
  // will be invoked after all other callbacks have been processed.
  void Start(Callback* aFinalCallback);

  // Set an internal flag indicating that a started job should finish as
  // soon as possible.
  void Cancel();

 protected:
  ServiceWorkerJob(Type aType, nsIPrincipal* aPrincipal,
                   const nsACString& aScope, nsCString aScriptSpec);

  virtual ~ServiceWorkerJob();

  // Invoke the result callbacks immediately.  The job must be in the
  // Started state or be canceled and in the Initial state.  The callbacks are
  // cleared after being invoked, so subsequent method calls have no effect.
  void InvokeResultCallbacks(ErrorResult& aRv);

  // Convenience method that converts to ErrorResult and calls real method.
  void InvokeResultCallbacks(nsresult aRv);

  // Indicate that the job has completed.  The must be called exactly
  // once after Start() has initiated job execution.  It may not be
  // called until Start() has returned.
  void Finish(ErrorResult& aRv);

  // Convenience method that converts to ErrorResult and calls real method.
  void Finish(nsresult aRv);

  // Specific job types should define AsyncExecute to begin their work.
  // All errors and successes must result in Finish() being called.
  virtual void AsyncExecute() = 0;

  const Type mType;
  nsCOMPtr<nsIPrincipal> mPrincipal;
  const nsCString mScope;
  const nsCString mScriptSpec;

 private:
  RefPtr<Callback> mFinalCallback;
  nsTArray<RefPtr<Callback>> mResultCallbackList;
  State mState;
  bool mCanceled;
  bool mResultCallbacksInvoked;

 public:
  NS_INLINE_DECL_REFCOUNTING(ServiceWorkerJob)
};

}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_serviceworkerjob_h