Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_context_watcher.cc
blobdce6b145d7f03bebd46a6ece0c4d5790c308b5bb
1 // Copyright 2015 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.
5 #include "content/browser/service_worker/service_worker_context_watcher.h"
7 #include "base/bind.h"
8 #include "base/containers/scoped_ptr_hash_map.h"
9 #include "content/browser/service_worker/service_worker_context_observer.h"
10 #include "content/browser/service_worker/service_worker_context_wrapper.h"
11 #include "content/browser/service_worker/service_worker_version.h"
12 #include "content/common/service_worker/service_worker_types.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/common/console_message_level.h"
15 #include "url/gurl.h"
17 namespace content {
18 namespace {
20 bool IsStoppedAndRedundant(const ServiceWorkerVersionInfo& version_info) {
21 return version_info.running_status ==
22 content::ServiceWorkerVersion::STOPPED &&
23 version_info.status == content::ServiceWorkerVersion::REDUNDANT;
26 } // namespace
28 ServiceWorkerContextWatcher::ServiceWorkerContextWatcher(
29 scoped_refptr<ServiceWorkerContextWrapper> context,
30 const WorkerRegistrationUpdatedCallback& registration_callback,
31 const WorkerVersionUpdatedCallback& version_callback,
32 const WorkerErrorReportedCallback& error_callback)
33 : context_(context),
34 registration_callback_(registration_callback),
35 version_callback_(version_callback),
36 error_callback_(error_callback) {
37 DCHECK_CURRENTLY_ON(BrowserThread::UI);
40 void ServiceWorkerContextWatcher::Start() {
41 DCHECK_CURRENTLY_ON(BrowserThread::UI);
42 BrowserThread::PostTask(
43 BrowserThread::IO, FROM_HERE,
44 base::Bind(&ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread,
45 this));
48 void ServiceWorkerContextWatcher::Stop() {
49 DCHECK_CURRENTLY_ON(BrowserThread::UI);
50 BrowserThread::PostTask(
51 BrowserThread::IO, FROM_HERE,
52 base::Bind(&ServiceWorkerContextWatcher::StopOnIOThread, this));
55 void ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread() {
56 DCHECK_CURRENTLY_ON(BrowserThread::IO);
57 context_->GetAllRegistrations(base::Bind(
58 &ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread, this));
61 void ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread(
62 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
63 DCHECK_CURRENTLY_ON(BrowserThread::IO);
64 context_->AddObserver(this);
66 base::ScopedPtrHashMap<int64, scoped_ptr<ServiceWorkerRegistrationInfo>>
67 registration_info_map;
68 for (const auto& registration : stored_registrations)
69 StoreRegistrationInfo(registration, &registration_info_map);
70 for (const auto& registration : context_->GetAllLiveRegistrationInfo())
71 StoreRegistrationInfo(registration, &registration_info_map);
72 for (const auto& version : context_->GetAllLiveVersionInfo())
73 StoreVersionInfo(version);
75 std::vector<ServiceWorkerRegistrationInfo> registrations;
76 registrations.reserve(registration_info_map.size());
77 for (const auto& registration_id_info_pair : registration_info_map)
78 registrations.push_back(*registration_id_info_pair.second);
80 std::vector<ServiceWorkerVersionInfo> versions;
81 versions.reserve(version_info_map_.size());
83 for (auto version_it = version_info_map_.begin();
84 version_it != version_info_map_.end();) {
85 versions.push_back(*version_it->second);
86 if (IsStoppedAndRedundant(*version_it->second))
87 version_info_map_.erase(version_it++);
88 else
89 ++version_it;
92 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
93 base::Bind(registration_callback_, registrations));
94 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
95 base::Bind(version_callback_, versions));
98 void ServiceWorkerContextWatcher::StopOnIOThread() {
99 DCHECK_CURRENTLY_ON(BrowserThread::IO);
100 context_->RemoveObserver(this);
103 ServiceWorkerContextWatcher::~ServiceWorkerContextWatcher() {
106 void ServiceWorkerContextWatcher::StoreRegistrationInfo(
107 const ServiceWorkerRegistrationInfo& registration_info,
108 base::ScopedPtrHashMap<int64, scoped_ptr<ServiceWorkerRegistrationInfo>>*
109 info_map) {
110 DCHECK_CURRENTLY_ON(BrowserThread::IO);
111 if (registration_info.registration_id == kInvalidServiceWorkerRegistrationId)
112 return;
113 info_map->set(registration_info.registration_id,
114 scoped_ptr<ServiceWorkerRegistrationInfo>(
115 new ServiceWorkerRegistrationInfo(registration_info)));
116 StoreVersionInfo(registration_info.active_version);
117 StoreVersionInfo(registration_info.waiting_version);
118 StoreVersionInfo(registration_info.installing_version);
121 void ServiceWorkerContextWatcher::StoreVersionInfo(
122 const ServiceWorkerVersionInfo& version_info) {
123 DCHECK_CURRENTLY_ON(BrowserThread::IO);
124 if (version_info.version_id == kInvalidServiceWorkerVersionId)
125 return;
126 version_info_map_.set(version_info.version_id,
127 scoped_ptr<ServiceWorkerVersionInfo>(
128 new ServiceWorkerVersionInfo(version_info)));
131 void ServiceWorkerContextWatcher::SendRegistrationInfo(
132 int64 registration_id,
133 const GURL& pattern,
134 ServiceWorkerRegistrationInfo::DeleteFlag delete_flag) {
135 std::vector<ServiceWorkerRegistrationInfo> registrations;
136 registrations.push_back(
137 ServiceWorkerRegistrationInfo(pattern, registration_id, delete_flag));
138 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
139 base::Bind(registration_callback_, registrations));
142 void ServiceWorkerContextWatcher::SendVersionInfo(
143 const ServiceWorkerVersionInfo& version_info) {
144 DCHECK_CURRENTLY_ON(BrowserThread::IO);
145 std::vector<ServiceWorkerVersionInfo> versions;
146 versions.push_back(version_info);
147 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
148 base::Bind(version_callback_, versions));
151 void ServiceWorkerContextWatcher::OnNewLiveRegistration(int64 registration_id,
152 const GURL& pattern) {
153 SendRegistrationInfo(registration_id, pattern,
154 ServiceWorkerRegistrationInfo::IS_NOT_DELETED);
157 void ServiceWorkerContextWatcher::OnNewLiveVersion(int64 version_id,
158 int64 registration_id,
159 const GURL& script_url) {
160 if (ServiceWorkerVersionInfo* version = version_info_map_.get(version_id)) {
161 DCHECK_EQ(version->registration_id, registration_id);
162 DCHECK_EQ(version->script_url, script_url);
163 return;
166 scoped_ptr<ServiceWorkerVersionInfo> version(new ServiceWorkerVersionInfo());
167 version->version_id = version_id;
168 version->registration_id = registration_id;
169 version->script_url = script_url;
170 SendVersionInfo(*version);
171 if (!IsStoppedAndRedundant(*version))
172 version_info_map_.set(version_id, version.Pass());
175 void ServiceWorkerContextWatcher::OnRunningStateChanged(
176 int64 version_id,
177 content::ServiceWorkerVersion::RunningStatus running_status) {
178 ServiceWorkerVersionInfo* version = version_info_map_.get(version_id);
179 DCHECK(version);
180 if (version->running_status == running_status)
181 return;
182 version->running_status = running_status;
183 SendVersionInfo(*version);
184 if (IsStoppedAndRedundant(*version))
185 version_info_map_.erase(version_id);
188 void ServiceWorkerContextWatcher::OnVersionStateChanged(
189 int64 version_id,
190 content::ServiceWorkerVersion::Status status) {
191 ServiceWorkerVersionInfo* version = version_info_map_.get(version_id);
192 DCHECK(version);
193 if (version->status == status)
194 return;
195 version->status = status;
196 SendVersionInfo(*version);
197 if (IsStoppedAndRedundant(*version))
198 version_info_map_.erase(version_id);
201 void ServiceWorkerContextWatcher::OnMainScriptHttpResponseInfoSet(
202 int64 version_id,
203 base::Time script_response_time,
204 base::Time script_last_modified) {
205 ServiceWorkerVersionInfo* version = version_info_map_.get(version_id);
206 DCHECK(version);
207 version->script_response_time = script_response_time;
208 version->script_last_modified = script_last_modified;
209 SendVersionInfo(*version);
212 void ServiceWorkerContextWatcher::OnErrorReported(int64 version_id,
213 int process_id,
214 int thread_id,
215 const ErrorInfo& info) {
216 int64 registration_id = kInvalidServiceWorkerRegistrationId;
217 if (ServiceWorkerVersionInfo* version = version_info_map_.get(version_id))
218 registration_id = version->registration_id;
219 BrowserThread::PostTask(
220 BrowserThread::UI, FROM_HERE,
221 base::Bind(error_callback_, registration_id, version_id, info));
224 void ServiceWorkerContextWatcher::OnReportConsoleMessage(
225 int64 version_id,
226 int process_id,
227 int thread_id,
228 const ConsoleMessage& message) {
229 if (message.message_level != CONSOLE_MESSAGE_LEVEL_ERROR)
230 return;
231 int64 registration_id = kInvalidServiceWorkerRegistrationId;
232 if (ServiceWorkerVersionInfo* version = version_info_map_.get(version_id))
233 registration_id = version->registration_id;
234 BrowserThread::PostTask(
235 BrowserThread::UI, FROM_HERE,
236 base::Bind(error_callback_, registration_id, version_id,
237 ErrorInfo(message.message, message.line_number, -1,
238 message.source_url)));
241 void ServiceWorkerContextWatcher::OnControlleeAdded(
242 int64 version_id,
243 const std::string& uuid,
244 int process_id,
245 int route_id,
246 ServiceWorkerProviderType type) {
247 ServiceWorkerVersionInfo* version = version_info_map_.get(version_id);
248 DCHECK(version);
249 version->clients[uuid] =
250 ServiceWorkerVersionInfo::ClientInfo(process_id, route_id, type);
251 SendVersionInfo(*version);
254 void ServiceWorkerContextWatcher::OnControlleeRemoved(int64 version_id,
255 const std::string& uuid) {
256 ServiceWorkerVersionInfo* version = version_info_map_.get(version_id);
257 if (!version)
258 return;
259 version->clients.erase(uuid);
260 SendVersionInfo(*version);
263 void ServiceWorkerContextWatcher::OnRegistrationStored(int64 registration_id,
264 const GURL& pattern) {
265 SendRegistrationInfo(registration_id, pattern,
266 ServiceWorkerRegistrationInfo::IS_NOT_DELETED);
269 void ServiceWorkerContextWatcher::OnRegistrationDeleted(int64 registration_id,
270 const GURL& pattern) {
271 SendRegistrationInfo(registration_id, pattern,
272 ServiceWorkerRegistrationInfo::IS_DELETED);
275 } // namespace content