service_worker_context_adapter.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. // Copyright 2020 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. #include "components/performance_manager/service_worker_context_adapter.h"
  5. #include "base/check_op.h"
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/notreached.h"
  8. #include "base/observer_list.h"
  9. #include "base/scoped_observation.h"
  10. #include "content/public/browser/render_process_host.h"
  11. #include "content/public/browser/render_process_host_observer.h"
  12. namespace performance_manager {
  13. // ServiceWorkerContextAdapter::RunningServiceWorker ---------------------------
  14. // Observes when the render process of a running service worker exits and
  15. // notifies its owner.
  16. class ServiceWorkerContextAdapter::RunningServiceWorker
  17. : content::RenderProcessHostObserver {
  18. public:
  19. RunningServiceWorker(int64_t version_id,
  20. ServiceWorkerContextAdapter* adapter);
  21. ~RunningServiceWorker() override;
  22. void Subscribe(content::RenderProcessHost* worker_process_host);
  23. void Unsubscribe();
  24. void RenderProcessExited(
  25. content::RenderProcessHost* host,
  26. const content::ChildProcessTerminationInfo& info) override;
  27. void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
  28. private:
  29. // The version ID of the service worker.
  30. int const version_id_;
  31. // The adapter that owns |this|. Notified when RenderProcessExited() is
  32. // called.
  33. const raw_ptr<ServiceWorkerContextAdapter> adapter_;
  34. base::ScopedObservation<content::RenderProcessHost,
  35. content::RenderProcessHostObserver>
  36. scoped_observation_{this};
  37. };
  38. ServiceWorkerContextAdapter::RunningServiceWorker::RunningServiceWorker(
  39. int64_t version_id,
  40. ServiceWorkerContextAdapter* adapter)
  41. : version_id_(version_id), adapter_(adapter) {}
  42. ServiceWorkerContextAdapter::RunningServiceWorker::~RunningServiceWorker() {
  43. DCHECK(!scoped_observation_.IsObserving());
  44. }
  45. void ServiceWorkerContextAdapter::RunningServiceWorker::Subscribe(
  46. content::RenderProcessHost* worker_process_host) {
  47. DCHECK(!scoped_observation_.IsObserving());
  48. scoped_observation_.Observe(worker_process_host);
  49. }
  50. void ServiceWorkerContextAdapter::RunningServiceWorker::Unsubscribe() {
  51. DCHECK(scoped_observation_.IsObserving());
  52. scoped_observation_.Reset();
  53. }
  54. void ServiceWorkerContextAdapter::RunningServiceWorker::RenderProcessExited(
  55. content::RenderProcessHost* host,
  56. const content::ChildProcessTerminationInfo& info) {
  57. adapter_->OnRenderProcessExited(version_id_);
  58. /* This object is deleted inside the above, don't touch "this". */
  59. }
  60. void ServiceWorkerContextAdapter::RunningServiceWorker::
  61. RenderProcessHostDestroyed(content::RenderProcessHost* host) {
  62. NOTREACHED();
  63. }
  64. // ServiceWorkerContextAdapter::RunningServiceWorker ---------------------------
  65. ServiceWorkerContextAdapter::ServiceWorkerContextAdapter(
  66. content::ServiceWorkerContext* underlying_context) {
  67. scoped_underlying_context_observation_.Observe(underlying_context);
  68. }
  69. ServiceWorkerContextAdapter::~ServiceWorkerContextAdapter() {
  70. // Clean up any outstanding running service worker process subscriptions.
  71. for (const auto& item : running_service_workers_)
  72. item.second->Unsubscribe();
  73. running_service_workers_.clear();
  74. }
  75. void ServiceWorkerContextAdapter::AddObserver(
  76. content::ServiceWorkerContextObserver* observer) {
  77. observer_list_.AddObserver(observer);
  78. }
  79. void ServiceWorkerContextAdapter::RemoveObserver(
  80. content::ServiceWorkerContextObserver* observer) {
  81. observer_list_.RemoveObserver(observer);
  82. }
  83. void ServiceWorkerContextAdapter::RegisterServiceWorker(
  84. const GURL& script_url,
  85. const blink::StorageKey& key,
  86. const blink::mojom::ServiceWorkerRegistrationOptions& options,
  87. StatusCodeCallback callback) {
  88. NOTIMPLEMENTED();
  89. }
  90. void ServiceWorkerContextAdapter::UnregisterServiceWorker(
  91. const GURL& scope,
  92. const blink::StorageKey& key,
  93. ResultCallback callback) {
  94. NOTIMPLEMENTED();
  95. }
  96. content::ServiceWorkerExternalRequestResult
  97. ServiceWorkerContextAdapter::StartingExternalRequest(
  98. int64_t service_worker_version_id,
  99. content::ServiceWorkerExternalRequestTimeoutType timeout_type,
  100. const std::string& request_uuid) {
  101. NOTIMPLEMENTED();
  102. return content::ServiceWorkerExternalRequestResult::kOk;
  103. }
  104. content::ServiceWorkerExternalRequestResult
  105. ServiceWorkerContextAdapter::FinishedExternalRequest(
  106. int64_t service_worker_version_id,
  107. const std::string& request_uuid) {
  108. NOTIMPLEMENTED();
  109. return content::ServiceWorkerExternalRequestResult::kOk;
  110. }
  111. size_t ServiceWorkerContextAdapter::CountExternalRequestsForTest(
  112. const blink::StorageKey& key) {
  113. NOTIMPLEMENTED();
  114. return 0u;
  115. }
  116. bool ServiceWorkerContextAdapter::ExecuteScriptForTest(
  117. const std::string& script,
  118. int64_t version_id,
  119. content::ServiceWorkerScriptExecutionCallback callback) {
  120. NOTIMPLEMENTED();
  121. return false;
  122. }
  123. bool ServiceWorkerContextAdapter::MaybeHasRegistrationForStorageKey(
  124. const blink::StorageKey& key) {
  125. NOTIMPLEMENTED();
  126. return false;
  127. }
  128. void ServiceWorkerContextAdapter::GetAllOriginsInfo(
  129. GetUsageInfoCallback callback) {
  130. NOTIMPLEMENTED();
  131. }
  132. void ServiceWorkerContextAdapter::DeleteForStorageKey(
  133. const blink::StorageKey& key,
  134. ResultCallback callback) {
  135. NOTIMPLEMENTED();
  136. }
  137. void ServiceWorkerContextAdapter::CheckHasServiceWorker(
  138. const GURL& url,
  139. const blink::StorageKey& key,
  140. CheckHasServiceWorkerCallback callback) {
  141. NOTIMPLEMENTED();
  142. }
  143. void ServiceWorkerContextAdapter::CheckOfflineCapability(
  144. const GURL& url,
  145. const blink::StorageKey& key,
  146. CheckOfflineCapabilityCallback callback) {
  147. NOTIMPLEMENTED();
  148. }
  149. void ServiceWorkerContextAdapter::ClearAllServiceWorkersForTest(
  150. base::OnceClosure callback) {
  151. NOTIMPLEMENTED();
  152. }
  153. void ServiceWorkerContextAdapter::StartWorkerForScope(
  154. const GURL& scope,
  155. const blink::StorageKey& key,
  156. StartWorkerCallback info_callback,
  157. StatusCodeCallback status_callback) {
  158. NOTIMPLEMENTED();
  159. }
  160. bool ServiceWorkerContextAdapter::IsLiveRunningServiceWorker(
  161. int64_t service_worker_version_id) {
  162. NOTIMPLEMENTED();
  163. return false;
  164. }
  165. service_manager::InterfaceProvider&
  166. ServiceWorkerContextAdapter::GetRemoteInterfaces(
  167. int64_t service_worker_version_id) {
  168. NOTIMPLEMENTED();
  169. static service_manager::InterfaceProvider interface_provider(
  170. base::ThreadTaskRunnerHandle::Get());
  171. return interface_provider;
  172. }
  173. void ServiceWorkerContextAdapter::StartServiceWorkerAndDispatchMessage(
  174. const GURL& scope,
  175. const blink::StorageKey& key,
  176. blink::TransferableMessage message,
  177. ResultCallback result_callback) {
  178. NOTIMPLEMENTED();
  179. }
  180. void ServiceWorkerContextAdapter::StartServiceWorkerForNavigationHint(
  181. const GURL& document_url,
  182. const blink::StorageKey& key,
  183. StartServiceWorkerForNavigationHintCallback callback) {
  184. NOTIMPLEMENTED();
  185. }
  186. void ServiceWorkerContextAdapter::StopAllServiceWorkersForStorageKey(
  187. const blink::StorageKey& key) {
  188. NOTIMPLEMENTED();
  189. }
  190. void ServiceWorkerContextAdapter::StopAllServiceWorkers(
  191. base::OnceClosure callback) {
  192. NOTIMPLEMENTED();
  193. }
  194. const base::flat_map<int64_t /* version_id */,
  195. content::ServiceWorkerRunningInfo>&
  196. ServiceWorkerContextAdapter::GetRunningServiceWorkerInfos() {
  197. NOTIMPLEMENTED();
  198. static base::flat_map<int64_t /* version_id */,
  199. content::ServiceWorkerRunningInfo>
  200. unused;
  201. return unused;
  202. }
  203. void ServiceWorkerContextAdapter::OnRegistrationCompleted(const GURL& scope) {
  204. for (auto& observer : observer_list_)
  205. observer.OnRegistrationCompleted(scope);
  206. }
  207. void ServiceWorkerContextAdapter::OnRegistrationStored(int64_t registration_id,
  208. const GURL& scope) {
  209. for (auto& observer : observer_list_)
  210. observer.OnRegistrationStored(registration_id, scope);
  211. }
  212. void ServiceWorkerContextAdapter::OnVersionActivated(int64_t version_id,
  213. const GURL& scope) {
  214. for (auto& observer : observer_list_)
  215. observer.OnVersionActivated(version_id, scope);
  216. }
  217. void ServiceWorkerContextAdapter::OnVersionRedundant(int64_t version_id,
  218. const GURL& scope) {
  219. for (auto& observer : observer_list_)
  220. observer.OnVersionRedundant(version_id, scope);
  221. }
  222. void ServiceWorkerContextAdapter::OnVersionStartedRunning(
  223. int64_t version_id,
  224. const content::ServiceWorkerRunningInfo& running_info) {
  225. content::RenderProcessHost* worker_process_host =
  226. content::RenderProcessHost::FromID(running_info.render_process_id);
  227. // It's possible that the renderer is already gone since the notification
  228. // comes asynchronously. Ignore this service worker.
  229. if (!worker_process_host || !worker_process_host->IsInitializedAndNotDead()) {
  230. #if DCHECK_IS_ON()
  231. // A OnVersionStoppedRunning() notification is still expected to be sent.
  232. bool inserted = stopped_service_workers_.insert(version_id).second;
  233. DCHECK(inserted);
  234. #endif // DCHECK_IS_ON()
  235. return;
  236. }
  237. AddRunningServiceWorker(version_id, worker_process_host);
  238. for (auto& observer : observer_list_)
  239. observer.OnVersionStartedRunning(version_id, running_info);
  240. }
  241. void ServiceWorkerContextAdapter::OnVersionStoppedRunning(int64_t version_id) {
  242. bool removed = MaybeRemoveRunningServiceWorker(version_id);
  243. if (!removed) {
  244. #if DCHECK_IS_ON()
  245. // If this service worker could not be found, then it must be because its
  246. // render process exited early.
  247. size_t removed_count = stopped_service_workers_.erase(version_id);
  248. DCHECK_EQ(removed_count, 1u);
  249. #endif // DCHECK_IS_ON()
  250. return;
  251. }
  252. for (auto& observer : observer_list_)
  253. observer.OnVersionStoppedRunning(version_id);
  254. }
  255. void ServiceWorkerContextAdapter::OnControlleeAdded(
  256. int64_t version_id,
  257. const std::string& client_uuid,
  258. const content::ServiceWorkerClientInfo& client_info) {
  259. // If |client_uuid| is already marked as a client of |version_id|, the
  260. // notification is dropped.
  261. bool inserted =
  262. service_worker_clients_[version_id].insert(client_uuid).second;
  263. if (!inserted) {
  264. NOTREACHED();
  265. return;
  266. }
  267. for (auto& observer : observer_list_)
  268. observer.OnControlleeAdded(version_id, client_uuid, client_info);
  269. }
  270. void ServiceWorkerContextAdapter::OnControlleeRemoved(
  271. int64_t version_id,
  272. const std::string& client_uuid) {
  273. // If |client_uuid| is not already marked as a client of |version_id|, the
  274. // notification is dropped.
  275. auto it = service_worker_clients_.find(version_id);
  276. if (it == service_worker_clients_.end()) {
  277. NOTREACHED();
  278. return;
  279. }
  280. size_t removed = it->second.erase(client_uuid);
  281. if (!removed) {
  282. NOTREACHED();
  283. return;
  284. }
  285. // If a service worker no longer has any clients, it is removed entirely from
  286. // |service_worker_clients_|.
  287. if (it->second.empty())
  288. service_worker_clients_.erase(it);
  289. for (auto& observer : observer_list_)
  290. observer.OnControlleeRemoved(version_id, client_uuid);
  291. }
  292. void ServiceWorkerContextAdapter::OnNoControllees(int64_t version_id,
  293. const GURL& scope) {
  294. for (auto& observer : observer_list_)
  295. observer.OnNoControllees(version_id, scope);
  296. }
  297. void ServiceWorkerContextAdapter::OnControlleeNavigationCommitted(
  298. int64_t version_id,
  299. const std::string& client_uuid,
  300. content::GlobalRenderFrameHostId render_frame_host_id) {
  301. // The navigation committed notification should not be sent if the frame is
  302. // not already a client of |version_id|.
  303. auto it = service_worker_clients_.find(version_id);
  304. if (it == service_worker_clients_.end()) {
  305. NOTREACHED();
  306. return;
  307. }
  308. if (it->second.find(client_uuid) == it->second.end()) {
  309. NOTREACHED();
  310. return;
  311. }
  312. for (auto& observer : observer_list_)
  313. observer.OnControlleeNavigationCommitted(version_id, client_uuid,
  314. render_frame_host_id);
  315. }
  316. void ServiceWorkerContextAdapter::OnReportConsoleMessage(
  317. int64_t version_id,
  318. const GURL& scope,
  319. const content::ConsoleMessage& message) {
  320. for (auto& observer : observer_list_)
  321. observer.OnReportConsoleMessage(version_id, scope, message);
  322. }
  323. void ServiceWorkerContextAdapter::OnDestruct(ServiceWorkerContext* context) {
  324. for (auto& observer : observer_list_)
  325. observer.OnDestruct(context);
  326. }
  327. void ServiceWorkerContextAdapter::OnRenderProcessExited(int64_t version_id) {
  328. bool removed = MaybeRemoveRunningServiceWorker(version_id);
  329. DCHECK(removed);
  330. for (auto& observer : observer_list_)
  331. observer.OnVersionStoppedRunning(version_id);
  332. #if DCHECK_IS_ON()
  333. // Now expect that OnVersionStoppedRunning() will be called for that
  334. // version_id.
  335. bool inserted = stopped_service_workers_.insert(version_id).second;
  336. DCHECK(inserted);
  337. #endif // DCHECK_IS_ON()
  338. }
  339. void ServiceWorkerContextAdapter::AddRunningServiceWorker(
  340. int64_t version_id,
  341. content::RenderProcessHost* worker_process_host) {
  342. std::unique_ptr<ServiceWorkerContextAdapter::RunningServiceWorker>
  343. running_service_worker =
  344. std::make_unique<RunningServiceWorker>(version_id, this);
  345. running_service_worker->Subscribe(worker_process_host);
  346. bool inserted = running_service_workers_
  347. .emplace(version_id, std::move(running_service_worker))
  348. .second;
  349. DCHECK(inserted);
  350. }
  351. bool ServiceWorkerContextAdapter::MaybeRemoveRunningServiceWorker(
  352. int64_t version_id) {
  353. auto it = running_service_workers_.find(version_id);
  354. if (it == running_service_workers_.end())
  355. return false;
  356. it->second->Unsubscribe();
  357. running_service_workers_.erase(it);
  358. return true;
  359. }
  360. } // namespace performance_manager