• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
6 #define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
7 
8 #include <map>
9 #include <vector>
10 
11 #include "base/basictypes.h"
12 #include "base/callback_forward.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/logging.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/observer_list.h"
18 #include "base/strings/string16.h"
19 #include "content/common/content_export.h"
20 #include "content/common/service_worker/service_worker_status_code.h"
21 #include "url/gurl.h"
22 
23 struct EmbeddedWorkerMsg_StartWorker_Params;
24 
25 namespace IPC {
26 class Message;
27 }
28 
29 namespace content {
30 
31 class EmbeddedWorkerRegistry;
32 class ServiceWorkerContextCore;
33 struct ServiceWorkerFetchRequest;
34 
35 // This gives an interface to control one EmbeddedWorker instance, which
36 // may be 'in-waiting' or running in one of the child processes added by
37 // AddProcessReference().
38 class CONTENT_EXPORT EmbeddedWorkerInstance {
39  public:
40   typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
41   enum Status {
42     STOPPED,
43     STARTING,
44     RUNNING,
45     STOPPING,
46   };
47 
48   class Listener {
49    public:
~Listener()50     virtual ~Listener() {}
51     virtual void OnStarted() = 0;
52     virtual void OnStopped() = 0;
OnReportException(const base::string16 & error_message,int line_number,int column_number,const GURL & source_url)53     virtual void OnReportException(const base::string16& error_message,
54                                    int line_number,
55                                    int column_number,
56                                    const GURL& source_url) {}
OnReportConsoleMessage(int source_identifier,int message_level,const base::string16 & message,int line_number,const GURL & source_url)57     virtual void OnReportConsoleMessage(int source_identifier,
58                                         int message_level,
59                                         const base::string16& message,
60                                         int line_number,
61                                         const GURL& source_url) {}
62     // These should return false if the message is not handled by this
63     // listener. (TODO(kinuko): consider using IPC::Listener interface)
64     // TODO(kinuko): Deprecate OnReplyReceived.
65     virtual bool OnMessageReceived(const IPC::Message& message) = 0;
66   };
67 
68   ~EmbeddedWorkerInstance();
69 
70   // Starts the worker. It is invalid to call this when the worker is not in
71   // STOPPED status. |callback| is invoked when the worker's process is created
72   // if necessary and the IPC to evaluate the worker's script is sent.
73   // Observer::OnStarted() is run when the worker is actually started.
74   void Start(int64 service_worker_version_id,
75              const GURL& scope,
76              const GURL& script_url,
77              const std::vector<int>& possible_process_ids,
78              const StatusCallback& callback);
79 
80   // Stops the worker. It is invalid to call this when the worker is
81   // not in STARTING or RUNNING status.
82   // This returns false if stopping a worker fails immediately, e.g. when
83   // IPC couldn't be sent to the worker.
84   ServiceWorkerStatusCode Stop();
85 
86   // Sends |message| to the embedded worker running in the child process.
87   // It is invalid to call this while the worker is not in RUNNING status.
88   ServiceWorkerStatusCode SendMessage(const IPC::Message& message);
89 
90   // Add or remove |process_id| to the internal process set where this
91   // worker can be started.
92   void AddProcessReference(int process_id);
93   void ReleaseProcessReference(int process_id);
HasProcessToRun()94   bool HasProcessToRun() const { return !process_refs_.empty(); }
95 
embedded_worker_id()96   int embedded_worker_id() const { return embedded_worker_id_; }
status()97   Status status() const { return status_; }
process_id()98   int process_id() const { return process_id_; }
thread_id()99   int thread_id() const { return thread_id_; }
worker_devtools_agent_route_id()100   int worker_devtools_agent_route_id() const {
101     return worker_devtools_agent_route_id_;
102   }
103 
104   void AddListener(Listener* listener);
105   void RemoveListener(Listener* listener);
106 
107  private:
108   typedef ObserverList<Listener> ListenerList;
109 
110   friend class EmbeddedWorkerRegistry;
111   FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop);
112   FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, SortProcesses);
113 
114   typedef std::map<int, int> ProcessRefMap;
115 
116   // Constructor is called via EmbeddedWorkerRegistry::CreateWorker().
117   // This instance holds a ref of |registry|.
118   EmbeddedWorkerInstance(base::WeakPtr<ServiceWorkerContextCore> context,
119                          int embedded_worker_id);
120 
121   // Called back from ServiceWorkerProcessManager after Start() passes control
122   // to the UI thread to acquire a reference to the process.
123   static void RunProcessAllocated(
124       base::WeakPtr<EmbeddedWorkerInstance> instance,
125       base::WeakPtr<ServiceWorkerContextCore> context,
126       scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
127       const EmbeddedWorkerInstance::StatusCallback& callback,
128       ServiceWorkerStatusCode status,
129       int process_id);
130   void ProcessAllocated(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
131                         const StatusCallback& callback,
132                         int process_id,
133                         ServiceWorkerStatusCode status);
134   // Called back after ProcessAllocated() passes control to the UI thread to
135   // register to WorkerDevToolsManager.
136   void SendStartWorker(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
137                        const StatusCallback& callback,
138                        int worker_devtools_agent_route_id,
139                        bool pause_on_start);
140 
141   // Called back from Registry when the worker instance has ack'ed that
142   // it finished loading the script.
143   void OnScriptLoaded();
144 
145   // Called back from Registry when the worker instance has ack'ed that
146   // it failed to load the script.
147   void OnScriptLoadFailed();
148 
149   // Called back from Registry when the worker instance has ack'ed that
150   // its WorkerGlobalScope is actually started and parsed on |thread_id| in the
151   // child process.
152   // This will change the internal status from STARTING to RUNNING.
153   void OnStarted(int thread_id);
154 
155   // Called back from Registry when the worker instance has ack'ed that
156   // its WorkerGlobalScope is actually stopped in the child process.
157   // This will change the internal status from STARTING or RUNNING to
158   // STOPPED.
159   void OnStopped();
160 
161   // Called back from Registry when the worker instance sends message
162   // to the browser (i.e. EmbeddedWorker observers).
163   // Returns false if the message is not handled.
164   bool OnMessageReceived(const IPC::Message& message);
165 
166   // Called back from Registry when the worker instance reports the exception.
167   void OnReportException(const base::string16& error_message,
168                          int line_number,
169                          int column_number,
170                          const GURL& source_url);
171 
172   // Called back from Registry when the worker instance reports to the console.
173   void OnReportConsoleMessage(int source_identifier,
174                               int message_level,
175                               const base::string16& message,
176                               int line_number,
177                               const GURL& source_url);
178 
179   // Chooses a list of processes to try to start this worker in, ordered by how
180   // many clients are currently in those processes.
181   std::vector<int> SortProcesses(
182       const std::vector<int>& possible_process_ids) const;
183 
184   base::WeakPtr<ServiceWorkerContextCore> context_;
185   scoped_refptr<EmbeddedWorkerRegistry> registry_;
186   const int embedded_worker_id_;
187   Status status_;
188 
189   // Current running information. -1 indicates the worker is not running.
190   int process_id_;
191   int thread_id_;
192   int worker_devtools_agent_route_id_;
193 
194   ProcessRefMap process_refs_;
195   ListenerList listener_list_;
196 
197   base::WeakPtrFactory<EmbeddedWorkerInstance> weak_factory_;
198 
199   DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstance);
200 };
201 
202 }  // namespace content
203 
204 #endif  // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
205