blob: 9cc389c85adbb7be06a6d3cdcbd6582ebb8b21b9 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/performance_manager/service_worker_context_adapter.h"
#include "base/logging.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
namespace performance_manager {
// ServiceWorkerContextAdapter::RunningServiceWorker ---------------------------
// Observes when the render process of a running service worker exits and
// notifies its owner.
class ServiceWorkerContextAdapter::RunningServiceWorker
: content::RenderProcessHostObserver {
public:
RunningServiceWorker(int64_t version_id,
content::RenderProcessHost* worker_process_host,
ServiceWorkerContextAdapter* adapter);
~RunningServiceWorker() override;
void RenderProcessExited(
content::RenderProcessHost* host,
const content::ChildProcessTerminationInfo& info) override;
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
private:
// The version ID of the service worker.
int version_id_;
// The adapter that owns |this|. Notified when RenderProcessExited() is
// called.
ServiceWorkerContextAdapter* const adapter_;
ScopedObserver<content::RenderProcessHost, content::RenderProcessHostObserver>
scoped_render_process_host_observer_{this};
};
ServiceWorkerContextAdapter::RunningServiceWorker::RunningServiceWorker(
int64_t version_id,
content::RenderProcessHost* worker_process_host,
ServiceWorkerContextAdapter* adapter)
: version_id_(version_id), adapter_(adapter) {
scoped_render_process_host_observer_.Add(worker_process_host);
}
ServiceWorkerContextAdapter::RunningServiceWorker::~RunningServiceWorker() =
default;
void ServiceWorkerContextAdapter::RunningServiceWorker::RenderProcessExited(
content::RenderProcessHost* host,
const content::ChildProcessTerminationInfo& info) {
adapter_->OnRenderProcessExited(version_id_);
}
void ServiceWorkerContextAdapter::RunningServiceWorker::
RenderProcessHostDestroyed(content::RenderProcessHost* host) {
NOTREACHED();
}
// ServiceWorkerContextAdapter::RunningServiceWorker ---------------------------
ServiceWorkerContextAdapter::ServiceWorkerContextAdapter(
content::ServiceWorkerContext* underlying_context) {
scoped_underlying_context_observer_.Add(underlying_context);
}
ServiceWorkerContextAdapter::~ServiceWorkerContextAdapter() = default;
void ServiceWorkerContextAdapter::AddObserver(
content::ServiceWorkerContextObserver* observer) {
observer_list_.AddObserver(observer);
}
void ServiceWorkerContextAdapter::RemoveObserver(
content::ServiceWorkerContextObserver* observer) {
observer_list_.RemoveObserver(observer);
}
void ServiceWorkerContextAdapter::RegisterServiceWorker(
const GURL& script_url,
const blink::mojom::ServiceWorkerRegistrationOptions& options,
ResultCallback callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::UnregisterServiceWorker(
const GURL& scope,
ResultCallback callback) {
NOTIMPLEMENTED();
}
content::ServiceWorkerExternalRequestResult
ServiceWorkerContextAdapter::StartingExternalRequest(
int64_t service_worker_version_id,
const std::string& request_uuid) {
NOTIMPLEMENTED();
return content::ServiceWorkerExternalRequestResult::kOk;
}
content::ServiceWorkerExternalRequestResult
ServiceWorkerContextAdapter::FinishedExternalRequest(
int64_t service_worker_version_id,
const std::string& request_uuid) {
NOTIMPLEMENTED();
return content::ServiceWorkerExternalRequestResult::kOk;
}
void ServiceWorkerContextAdapter::CountExternalRequestsForTest(
const GURL& origin,
CountExternalRequestsCallback callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::GetAllOriginsInfo(
GetUsageInfoCallback callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::DeleteForOrigin(const GURL& origin_url,
ResultCallback callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::PerformStorageCleanup(
base::OnceClosure callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::CheckHasServiceWorker(
const GURL& url,
CheckHasServiceWorkerCallback callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::CheckOfflineCapability(
const GURL& url,
CheckOfflineCapabilityCallback callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::ClearAllServiceWorkersForTest(
base::OnceClosure callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::StartWorkerForScope(
const GURL& scope,
StartWorkerCallback info_callback,
base::OnceClosure failure_callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::StartServiceWorkerAndDispatchMessage(
const GURL& scope,
blink::TransferableMessage message,
ResultCallback result_callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::StartServiceWorkerForNavigationHint(
const GURL& document_url,
StartServiceWorkerForNavigationHintCallback callback) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::StopAllServiceWorkersForOrigin(
const GURL& origin) {
NOTIMPLEMENTED();
}
void ServiceWorkerContextAdapter::StopAllServiceWorkers(
base::OnceClosure callback) {
NOTIMPLEMENTED();
}
const base::flat_map<int64_t /* version_id */,
content::ServiceWorkerRunningInfo>&
ServiceWorkerContextAdapter::GetRunningServiceWorkerInfos() {
NOTIMPLEMENTED();
static base::flat_map<int64_t /* version_id */,
content::ServiceWorkerRunningInfo>
unused;
return unused;
}
void ServiceWorkerContextAdapter::OnRegistrationCompleted(const GURL& scope) {
for (auto& observer : observer_list_)
observer.OnRegistrationCompleted(scope);
}
void ServiceWorkerContextAdapter::OnRegistrationStored(int64_t registration_id,
const GURL& scope) {
for (auto& observer : observer_list_)
observer.OnRegistrationStored(registration_id, scope);
}
void ServiceWorkerContextAdapter::OnVersionActivated(int64_t version_id,
const GURL& scope) {
for (auto& observer : observer_list_)
observer.OnVersionActivated(version_id, scope);
}
void ServiceWorkerContextAdapter::OnVersionRedundant(int64_t version_id,
const GURL& scope) {
for (auto& observer : observer_list_)
observer.OnVersionRedundant(version_id, scope);
}
void ServiceWorkerContextAdapter::OnVersionStartedRunning(
int64_t version_id,
const content::ServiceWorkerRunningInfo& running_info) {
auto* worker_process_host =
content::RenderProcessHost::FromID(running_info.render_process_id);
// It's possible that the renderer is already gone since the notification
// comes asynchronously. Ignore this service worker.
if (!worker_process_host || !worker_process_host->IsReady()) {
#if DCHECK_IS_ON()
// A OnVersionStoppedRunning() notification is still expected to be sent.
bool inserted = stopped_service_workers_.insert(version_id).second;
DCHECK(inserted);
#endif // DCHECK_IS_ON()
return;
}
bool inserted =
running_service_workers_
.emplace(version_id, std::make_unique<RunningServiceWorker>(
version_id, worker_process_host, this))
.second;
DCHECK(inserted);
for (auto& observer : observer_list_)
observer.OnVersionStartedRunning(version_id, running_info);
}
void ServiceWorkerContextAdapter::OnVersionStoppedRunning(int64_t version_id) {
size_t removed = running_service_workers_.erase(version_id);
if (!removed) {
#if DCHECK_IS_ON()
// If this service worker could not be found, then it must be because its
// render process exited early.
size_t removed = stopped_service_workers_.erase(version_id);
DCHECK_EQ(removed, 1u);
#endif // DCHECK_IS_ON()
return;
}
for (auto& observer : observer_list_)
observer.OnVersionStoppedRunning(version_id);
}
void ServiceWorkerContextAdapter::OnNoControllees(int64_t version_id,
const GURL& scope) {
for (auto& observer : observer_list_)
observer.OnNoControllees(version_id, scope);
}
void ServiceWorkerContextAdapter::OnReportConsoleMessage(
int64_t version_id,
const content::ConsoleMessage& message) {
for (auto& observer : observer_list_)
observer.OnReportConsoleMessage(version_id, message);
}
void ServiceWorkerContextAdapter::OnDestruct(ServiceWorkerContext* context) {
for (auto& observer : observer_list_)
observer.OnDestruct(context);
}
void ServiceWorkerContextAdapter::OnRenderProcessExited(int64_t version_id) {
size_t removed = running_service_workers_.erase(version_id);
DCHECK_EQ(removed, 1u);
for (auto& observer : observer_list_)
observer.OnVersionStoppedRunning(version_id);
#if DCHECK_IS_ON()
// Now expect that OnVersionStoppedRunning() will be called for that
// version_id.
bool inserted = stopped_service_workers_.insert(version_id).second;
DCHECK(inserted);
#endif // DCHECK_IS_ON()
}
} // namespace performance_manager