| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/site_instance_group.h" |
| |
| #include "base/observer_list.h" |
| #include "content/browser/renderer_host/render_process_host_impl.h" |
| #include "content/browser/site_instance_impl.h" |
| #include "content/public/browser/render_process_host.h" |
| |
| namespace content { |
| |
| namespace { |
| SiteInstanceGroupId::Generator site_instance_group_id_generator; |
| } // namespace |
| |
| SiteInstanceGroup::SiteInstanceGroup(BrowsingInstance* browsing_instance, |
| RenderProcessHost* process) |
| : id_(site_instance_group_id_generator.GenerateNextId()), |
| browsing_instance_(browsing_instance), |
| process_(process->GetSafeRef()), |
| agent_scheduling_group_( |
| AgentSchedulingGroupHost::GetOrCreate(*this, *process) |
| ->GetSafeRef()) { |
| process->AddObserver(this); |
| } |
| |
| SiteInstanceGroup::~SiteInstanceGroup() { |
| process_->RemoveObserver(this); |
| } |
| |
| SiteInstanceGroupId SiteInstanceGroup::GetId() const { |
| return id_; |
| } |
| |
| base::SafeRef<SiteInstanceGroup> SiteInstanceGroup::GetSafeRef() { |
| return weak_ptr_factory_.GetSafeRef(); |
| } |
| |
| base::WeakPtr<SiteInstanceGroup> |
| SiteInstanceGroup::GetWeakPtrToAllowDangling() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| void SiteInstanceGroup::AddObserver(Observer* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void SiteInstanceGroup::RemoveObserver(Observer* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| void SiteInstanceGroup::AddSiteInstance(SiteInstanceImpl* site_instance) { |
| CHECK_EQ(browsing_instance_id(), site_instance->GetBrowsingInstanceId()); |
| site_instances_.insert(site_instance); |
| } |
| |
| void SiteInstanceGroup::RemoveSiteInstance(SiteInstanceImpl* site_instance) { |
| site_instances_.erase(site_instance); |
| if (site_instances_.empty()) |
| process_->Cleanup(); |
| } |
| |
| void SiteInstanceGroup::IncrementActiveFrameCount() { |
| active_frame_count_++; |
| } |
| |
| void SiteInstanceGroup::DecrementActiveFrameCount() { |
| if (--active_frame_count_ == 0) { |
| for (auto& observer : observers_) |
| observer.ActiveFrameCountIsZero(this); |
| } |
| } |
| |
| bool SiteInstanceGroup::IsRelatedSiteInstanceGroup(SiteInstanceGroup* group) { |
| return browsing_instance_id() == group->browsing_instance_id(); |
| } |
| |
| void SiteInstanceGroup::RenderProcessHostDestroyed(RenderProcessHost* host) { |
| DCHECK_EQ(process_->GetID(), host->GetID()); |
| process_->RemoveObserver(this); |
| |
| // Remove references to `this` from all SiteInstances in this group. That will |
| // cause `this` to be destructed, to enforce the invariant that a |
| // SiteInstanceGroup must have a RenderProcessHost. |
| for (auto* instance : site_instances_) |
| instance->ResetSiteInstanceGroup(); |
| } |
| |
| void SiteInstanceGroup::RenderProcessExited( |
| RenderProcessHost* host, |
| const ChildProcessTerminationInfo& info) { |
| for (auto& observer : observers_) |
| observer.RenderProcessGone(this, info); |
| } |
| |
| // static |
| SiteInstanceGroup* SiteInstanceGroup::CreateForTesting( |
| BrowserContext* browser_context, |
| RenderProcessHost* process) { |
| return new SiteInstanceGroup( |
| new BrowsingInstance(browser_context, |
| WebExposedIsolationInfo::CreateNonIsolated(), |
| /*is_guest=*/false, |
| /*is_fenced=*/false, /*coop_related_group=*/nullptr, |
| /*common_coop_origin=*/absl::nullopt), |
| process); |
| } |
| |
| // static |
| SiteInstanceGroup* SiteInstanceGroup::CreateForTesting( |
| SiteInstanceGroup* group, |
| RenderProcessHost* process) { |
| return new SiteInstanceGroup( |
| group->browsing_instance_for_testing(), // IN-TEST |
| process); |
| } |
| |
| void SiteInstanceGroup::WriteIntoTrace( |
| perfetto::TracedProto<TraceProto> proto) const { |
| proto->set_site_instance_group_id(GetId().value()); |
| proto->set_active_frame_count(active_frame_count()); |
| proto.Set(TraceProto::kProcess, process()); |
| } |
| |
| } // namespace content |