OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/embedded_worker_instance.h" | 5 #include "content/browser/service_worker/embedded_worker_instance.h" |
6 | 6 |
7 #include "content/browser/service_worker/embedded_worker_registry.h" | 7 #include "content/browser/service_worker/embedded_worker_registry.h" |
8 #include "content/common/service_worker/embedded_worker_messages.h" | 8 #include "content/common/service_worker/embedded_worker_messages.h" |
9 #include "ipc/ipc_message.h" | 9 #include "ipc/ipc_message.h" |
10 #include "url/gurl.h" | 10 #include "url/gurl.h" |
11 | 11 |
12 namespace content { | 12 namespace content { |
13 | 13 |
| 14 namespace { |
| 15 // Functor to sort by the .second element of a struct. |
| 16 struct SecondGreater { |
| 17 template <typename Value> |
| 18 bool operator()(const Value& lhs, const Value& rhs) { |
| 19 return lhs.second > rhs.second; |
| 20 } |
| 21 }; |
| 22 } // namespace |
| 23 |
14 EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { | 24 EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { |
15 registry_->RemoveWorker(process_id_, embedded_worker_id_); | 25 registry_->RemoveWorker(process_id_, embedded_worker_id_); |
16 } | 26 } |
17 | 27 |
18 ServiceWorkerStatusCode EmbeddedWorkerInstance::Start( | 28 void EmbeddedWorkerInstance::Start(int64 service_worker_version_id, |
19 int64 service_worker_version_id, | 29 const GURL& scope, |
20 const GURL& scope, | 30 const GURL& script_url, |
21 const GURL& script_url) { | 31 const std::vector<int>& possible_process_ids, |
| 32 const StatusCallback& callback) { |
22 DCHECK(status_ == STOPPED); | 33 DCHECK(status_ == STOPPED); |
23 if (!ChooseProcess()) | |
24 return SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND; | |
25 status_ = STARTING; | 34 status_ = STARTING; |
26 ServiceWorkerStatusCode status = | 35 std::vector<int> ordered_process_ids = SortProcesses(possible_process_ids); |
27 registry_->StartWorker(process_id_, | 36 registry_->StartWorker(ordered_process_ids, |
28 embedded_worker_id_, | 37 embedded_worker_id_, |
29 service_worker_version_id, | 38 service_worker_version_id, |
30 scope, | 39 scope, |
31 script_url); | 40 script_url, |
32 if (status != SERVICE_WORKER_OK) { | 41 callback); |
33 status_ = STOPPED; | |
34 process_id_ = -1; | |
35 } | |
36 return status; | |
37 } | 42 } |
38 | 43 |
39 ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() { | 44 ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() { |
40 DCHECK(status_ == STARTING || status_ == RUNNING); | 45 DCHECK(status_ == STARTING || status_ == RUNNING); |
41 ServiceWorkerStatusCode status = | 46 ServiceWorkerStatusCode status = |
42 registry_->StopWorker(process_id_, embedded_worker_id_); | 47 registry_->StopWorker(process_id_, embedded_worker_id_); |
43 if (status == SERVICE_WORKER_OK) | 48 if (status == SERVICE_WORKER_OK) |
44 status_ = STOPPING; | 49 status_ = STOPPING; |
45 return status; | 50 return status; |
46 } | 51 } |
(...skipping 26 matching lines...) Expand all Loading... |
73 EmbeddedWorkerInstance::EmbeddedWorkerInstance( | 78 EmbeddedWorkerInstance::EmbeddedWorkerInstance( |
74 EmbeddedWorkerRegistry* registry, | 79 EmbeddedWorkerRegistry* registry, |
75 int embedded_worker_id) | 80 int embedded_worker_id) |
76 : registry_(registry), | 81 : registry_(registry), |
77 embedded_worker_id_(embedded_worker_id), | 82 embedded_worker_id_(embedded_worker_id), |
78 status_(STOPPED), | 83 status_(STOPPED), |
79 process_id_(-1), | 84 process_id_(-1), |
80 thread_id_(-1) { | 85 thread_id_(-1) { |
81 } | 86 } |
82 | 87 |
| 88 void EmbeddedWorkerInstance::RecordProcessId(int process_id, |
| 89 ServiceWorkerStatusCode status) { |
| 90 DCHECK_EQ(process_id_, -1); |
| 91 if (status == SERVICE_WORKER_OK) { |
| 92 process_id_ = process_id; |
| 93 } else { |
| 94 status_ = STOPPED; |
| 95 } |
| 96 } |
| 97 |
83 void EmbeddedWorkerInstance::OnStarted(int thread_id) { | 98 void EmbeddedWorkerInstance::OnStarted(int thread_id) { |
84 // Stop is requested before OnStarted is sent back from the worker. | 99 // Stop is requested before OnStarted is sent back from the worker. |
85 if (status_ == STOPPING) | 100 if (status_ == STOPPING) |
86 return; | 101 return; |
87 DCHECK(status_ == STARTING); | 102 DCHECK(status_ == STARTING); |
88 status_ = RUNNING; | 103 status_ = RUNNING; |
89 thread_id_ = thread_id; | 104 thread_id_ = thread_id; |
90 FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted()); | 105 FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted()); |
91 } | 106 } |
92 | 107 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 } | 146 } |
132 | 147 |
133 void EmbeddedWorkerInstance::AddListener(Listener* listener) { | 148 void EmbeddedWorkerInstance::AddListener(Listener* listener) { |
134 listener_list_.AddObserver(listener); | 149 listener_list_.AddObserver(listener); |
135 } | 150 } |
136 | 151 |
137 void EmbeddedWorkerInstance::RemoveListener(Listener* listener) { | 152 void EmbeddedWorkerInstance::RemoveListener(Listener* listener) { |
138 listener_list_.RemoveObserver(listener); | 153 listener_list_.RemoveObserver(listener); |
139 } | 154 } |
140 | 155 |
141 bool EmbeddedWorkerInstance::ChooseProcess() { | 156 std::vector<int> EmbeddedWorkerInstance::SortProcesses( |
142 DCHECK_EQ(-1, process_id_); | 157 const std::vector<int>& possible_process_ids) const { |
143 // Naive implementation; chooses a process which has the biggest number of | 158 // Add the |possible_process_ids| to the existing process_refs_ since each one |
144 // associated providers (so that hopefully likely live longer). | 159 // is likely to take a reference once the SW starts up. |
145 ProcessRefMap::iterator max_ref_iter = process_refs_.end(); | 160 ProcessRefMap refs_with_new_ids = process_refs_; |
146 for (ProcessRefMap::iterator iter = process_refs_.begin(); | 161 for (std::vector<int>::const_iterator it = possible_process_ids.begin(); |
147 iter != process_refs_.end(); ++iter) { | 162 it != possible_process_ids.end(); |
148 if (max_ref_iter == process_refs_.end() || | 163 ++it) { |
149 max_ref_iter->second < iter->second) | 164 refs_with_new_ids[*it]++; |
150 max_ref_iter = iter; | |
151 } | 165 } |
152 if (max_ref_iter == process_refs_.end()) | 166 |
153 return false; | 167 std::vector<std::pair<int, int> > counted(refs_with_new_ids.begin(), |
154 process_id_ = max_ref_iter->first; | 168 refs_with_new_ids.end()); |
155 return true; | 169 // Sort descending by the reference count. |
| 170 std::sort(counted.begin(), counted.end(), SecondGreater()); |
| 171 |
| 172 std::vector<int> result(counted.size()); |
| 173 for (size_t i = 0; i < counted.size(); ++i) |
| 174 result[i] = counted[i].first; |
| 175 return result; |
156 } | 176 } |
157 | 177 |
158 } // namespace content | 178 } // namespace content |
OLD | NEW |