blob: 1539d7cc12fde94b4490146e4321471a20b30869 [file] [log] [blame]
// 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 "chrome/browser/ui/views/side_panel/side_panel_registry.h"
#include <algorithm>
#include <variant>
#include "base/auto_reset.h"
#include "base/containers/unique_ptr_adapters.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/tabs/public/tab_features.h"
#include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
#include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
#include "components/tabs/public/tab_interface.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/extension_id.h"
SidePanelRegistry::SidePanelRegistry(tabs::TabInterface* tab_interface)
: SidePanelEntryScope(SidePanelEntryScope::ScopeType::kTab),
owner_(tab_interface) {
CHECK(tab_interface);
}
SidePanelRegistry::SidePanelRegistry(
BrowserWindowInterface* browser_window_interface)
: SidePanelEntryScope(SidePanelEntryScope::ScopeType::kBrowser),
owner_(browser_window_interface) {
CHECK(browser_window_interface);
}
SidePanelRegistry::~SidePanelRegistry() = default;
// static
SidePanelRegistry* SidePanelRegistry::GetDeprecated(
content::WebContents* web_contents) {
tabs::TabInterface* tab = tabs::TabInterface::GetFromContents(web_contents);
return tab->GetTabFeatures()->side_panel_registry();
}
SidePanelEntry* SidePanelRegistry::GetEntryForKey(
const SidePanelEntry::Key& entry_key) {
auto it = std::ranges::find(entries_, entry_key, &SidePanelEntry::key);
return it == entries_.end() ? nullptr : it->get();
}
void SidePanelRegistry::ResetActiveEntryFor(SidePanelEntry::PanelType type) {
active_entries_[type].reset();
}
void SidePanelRegistry::ClearCachedEntryViews(SidePanelEntry::PanelType type) {
for (auto const& entry : entries_) {
if (entry->type() == type &&
(!active_entries_[type].has_value() ||
entry.get() != active_entries_[type].value())) {
entry.get()->ClearCachedView();
}
}
}
bool SidePanelRegistry::Register(std::unique_ptr<SidePanelEntry> entry) {
if (GetEntryForKey(entry->key())) {
return false;
}
// It's important to add `this` as an observer to `entry` before notifying
// SidePanelRegistryObservers of the entry's registration because some
// registry observers can call SidePanelEntryObserver methods for `entry`.
entry->set_scope(this);
entry->AddObserver(this);
entries_.push_back(std::move(entry));
return true;
}
bool SidePanelRegistry::Deregister(const SidePanelEntry::Key& key) {
auto* entry = GetEntryForKey(key);
// An observer can trigger this to be called while a deregister for the key
// is ongoing. An example is an observer listening to `OnSidePanelDidClose()`
// since a sidepanel can be closed during the deregistering process.
if (!entry || (deregistering_entry_key_.has_value() &&
deregistering_entry_key_.value() == key)) {
return false;
}
SidePanelEntry::PanelType panel_type = entry->type();
base::AutoReset<std::optional<SidePanelEntryKey>> deregistering_entry_key(
&deregistering_entry_key_, key);
entry->RemoveObserver(this);
entry->set_scope(nullptr);
if (active_entries_[panel_type].has_value() &&
entry->key() == active_entries_[panel_type].value()->key()) {
active_entries_[panel_type].reset();
}
// TODO(https://crbug.com/360163254): This is nullptr in
// BrowserWithTestWindowTest. When the test suite goes away the nullptr check
// can be removed.
if (auto* coordinator = GetCoordinator()) {
bool for_tab = get_scope_type() == SidePanelEntryScope::ScopeType::kTab;
// If the entry with the same key and scope is showing, synchronously close.
if (coordinator->IsSidePanelEntryShowing(key, for_tab)) {
coordinator->Close(/*suppress_animations=*/true, panel_type);
}
}
auto it = std::find_if(entries_.begin(), entries_.end(),
base::MatchesUniquePtr(entry));
if (it != entries_.end()) {
entries_.erase(it);
}
return true;
}
void SidePanelRegistry::SetActiveEntry(SidePanelEntry* entry) {
active_entries_[entry->type()] = entry;
}
std::optional<SidePanelEntry*> SidePanelRegistry::GetActiveEntryFor(
SidePanelEntry::PanelType type) {
return active_entries_[type];
}
void SidePanelRegistry::OnEntryShown(SidePanelEntry* entry) {
active_entries_[entry->type()] = entry;
}
const tabs::TabInterface& SidePanelRegistry::GetTabInterface() const {
CHECK_EQ(SidePanelEntryScope::ScopeType::kTab, get_scope_type());
return *std::get<tabs::TabInterface*>(owner_);
}
const BrowserWindowInterface& SidePanelRegistry::GetBrowserWindowInterface()
const {
return get_scope_type() == SidePanelEntryScope::ScopeType::kTab
? *std::get<tabs::TabInterface*>(owner_)
->GetBrowserWindowInterface()
: *std::get<BrowserWindowInterface*>(owner_);
}
SidePanelCoordinator* SidePanelRegistry::GetCoordinator() {
return GetBrowserWindowInterface().GetFeatures().side_panel_coordinator();
}