|  | // 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/breadcrumb_manager_browser_agent.h" | 
|  |  | 
|  | #include <optional> | 
|  |  | 
|  | #include "base/check_deref.h" | 
|  | #include "chrome/browser/breadcrumbs/breadcrumb_manager_keyed_service_factory.h" | 
|  | #include "chrome/browser/breadcrumbs/breadcrumb_manager_tab_helper.h" | 
|  | #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
|  | #include "components/breadcrumbs/core/breadcrumb_manager_keyed_service.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | int GetTabId(const content::WebContents* const web_contents) { | 
|  | CHECK(web_contents); | 
|  | const BreadcrumbManagerTabHelper* const tab_helper = | 
|  | BreadcrumbManagerTabHelper::FromWebContents(web_contents); | 
|  | CHECK(tab_helper); | 
|  | return tab_helper->GetUniqueId(); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | BreadcrumbManagerBrowserAgent::BreadcrumbManagerBrowserAgent( | 
|  | TabStripModel* tab_strip_model, | 
|  | content::BrowserContext* browser_context) | 
|  | : breadcrumb_manager_(CHECK_DEREF( | 
|  | BreadcrumbManagerKeyedServiceFactory::GetForBrowserContext( | 
|  | browser_context))) { | 
|  | tab_strip_model->AddObserver(this); | 
|  | } | 
|  |  | 
|  | BreadcrumbManagerBrowserAgent::~BreadcrumbManagerBrowserAgent() = default; | 
|  |  | 
|  | void BreadcrumbManagerBrowserAgent::PlatformLogEvent(const std::string& event) { | 
|  | breadcrumb_manager_->AddEvent(event); | 
|  | } | 
|  |  | 
|  | void BreadcrumbManagerBrowserAgent::OnTabStripModelChanged( | 
|  | TabStripModel* tab_strip_model, | 
|  | const TabStripModelChange& change, | 
|  | const TabStripSelectionChange& selection) { | 
|  | switch (change.type()) { | 
|  | case TabStripModelChange::kInserted: { | 
|  | const auto& inserted_tabs = change.GetInsert()->contents; | 
|  | const int num_inserted_tabs = inserted_tabs.size(); | 
|  | if (num_inserted_tabs == 1) { | 
|  | LogTabInsertedAt(GetTabId(inserted_tabs[0].contents), | 
|  | inserted_tabs[0].index, | 
|  | selection.active_tab_changed()); | 
|  | } else { | 
|  | LogTabsInserted(num_inserted_tabs); | 
|  | } | 
|  | return; | 
|  | } | 
|  | case TabStripModelChange::kRemoved: { | 
|  | const auto& closed_tabs = change.GetRemove()->contents; | 
|  | const int num_closed_tabs = closed_tabs.size(); | 
|  | if (num_closed_tabs == 1) { | 
|  | LogTabClosedAt(GetTabId(closed_tabs[0].contents), closed_tabs[0].index); | 
|  | } else { | 
|  | LogTabsClosed(num_closed_tabs); | 
|  | } | 
|  | return; | 
|  | } | 
|  | case TabStripModelChange::kMoved: { | 
|  | const auto* const move = change.GetMove(); | 
|  | LogTabMoved(GetTabId(move->contents), move->from_index, move->to_index); | 
|  | return; | 
|  | } | 
|  | case TabStripModelChange::kReplaced: { | 
|  | const auto* const replace = change.GetReplace(); | 
|  | LogTabReplaced(GetTabId(replace->old_contents), | 
|  | GetTabId(replace->new_contents), replace->index); | 
|  | return; | 
|  | } | 
|  | case TabStripModelChange::kSelectionOnly: { | 
|  | if (selection.active_tab_changed()) { | 
|  | std::optional<int> old_tab_id = | 
|  | selection.old_contents | 
|  | ? std::make_optional(GetTabId(selection.old_contents)) | 
|  | : std::nullopt; | 
|  | std::optional<int> new_tab_id = | 
|  | selection.new_contents | 
|  | ? std::make_optional(GetTabId(selection.new_contents)) | 
|  | : std::nullopt; | 
|  | LogActiveTabChanged(old_tab_id, new_tab_id, | 
|  | selection.new_model.active()); | 
|  | } | 
|  | return; | 
|  | } | 
|  | } | 
|  | } |