|  | // Copyright 2025 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_ANDROID_H_ | 
|  | #define CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_ANDROID_H_ | 
|  |  | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <set> | 
|  | #include <string> | 
|  |  | 
|  | #include "base/memory/raw_ptr.h" | 
|  | #include "base/scoped_multi_source_observation.h" | 
|  | #include "chrome/browser/ui/android/tab_model/tab_model_list_observer.h" | 
|  | #include "chrome/browser/ui/android/tab_model/tab_model_observer.h" | 
|  | #include "content/public/browser/web_contents_observer.h" | 
|  | #include "extensions/browser/event_router.h" | 
|  | #include "url/gurl.h" | 
|  |  | 
|  | class Profile; | 
|  | class TabAndroid; | 
|  | class TabModel; | 
|  |  | 
|  | namespace content { | 
|  | class WebContents; | 
|  | } | 
|  |  | 
|  | namespace extensions { | 
|  |  | 
|  | // TabsEventRouterAndroid listens to tab events on Android and routes them to | 
|  | // listeners inside extension process renderers. | 
|  | // | 
|  | // TODO(crbug.com/427503497): This class is a temporary solution to unblock the | 
|  | // Tabs API on desktop Android. It can be deleted once TabsEventRouter works on | 
|  | // desktop Android. | 
|  | class TabsEventRouterAndroid : public TabModelListObserver, | 
|  | public TabModelObserver { | 
|  | public: | 
|  | explicit TabsEventRouterAndroid(Profile* profile); | 
|  | TabsEventRouterAndroid(const TabsEventRouterAndroid&) = delete; | 
|  | TabsEventRouterAndroid& operator=(const TabsEventRouterAndroid&) = delete; | 
|  | ~TabsEventRouterAndroid() override; | 
|  |  | 
|  | // TabModelListObserver: | 
|  | void OnTabModelAdded(TabModel* tab_model) override; | 
|  | void OnTabModelRemoved(TabModel* tab_model) override; | 
|  |  | 
|  | // TabModelObserver: | 
|  | void DidAddTab(TabAndroid* tab, TabModel::TabLaunchType type) override; | 
|  | void TabRemoved(TabAndroid* tab) override; | 
|  |  | 
|  | private: | 
|  | class TabEntry : public content::WebContentsObserver { | 
|  | public: | 
|  | TabEntry(TabsEventRouterAndroid* router, content::WebContents* contents); | 
|  | ~TabEntry() override; | 
|  |  | 
|  | // content::WebContentsObserver: | 
|  | void DidStopLoading() override; | 
|  | void TitleWasSet(content::NavigationEntry* entry) override; | 
|  | void WebContentsDestroyed() override; | 
|  |  | 
|  | const raw_ptr<TabsEventRouterAndroid> router_; | 
|  | GURL url_; | 
|  | }; | 
|  |  | 
|  | void TabCreatedAt(content::WebContents* contents, bool active); | 
|  |  | 
|  | // Internal processing of tab updated events. Intended to be called when | 
|  | // there's any changed property. | 
|  | void TabUpdated(TabEntry* entry, | 
|  | std::set<std::string> changed_property_names); | 
|  |  | 
|  | void DispatchTabUpdatedEvent(content::WebContents* contents, | 
|  | std::set<std::string> changed_property_names); | 
|  | void DispatchEvent(events::HistogramValue histogram_value, | 
|  | const std::string& event_name, | 
|  | base::Value::List args, | 
|  | EventRouter::UserGestureState user_gesture); | 
|  |  | 
|  | void RegisterForTabNotifications(content::WebContents* contents); | 
|  |  | 
|  | // Gets the TabEntry for the given `contents`. Returns TabEntry* if found, | 
|  | // nullptr if not. | 
|  | TabEntry* GetTabEntry(content::WebContents* contents); | 
|  |  | 
|  | raw_ptr<Profile> profile_; | 
|  |  | 
|  | base::ScopedMultiSourceObservation<TabModel, TabModelObserver> | 
|  | tab_model_observations_{this}; | 
|  |  | 
|  | // The map is keyed by tab id. | 
|  | using TabEntryMap = std::map<int, std::unique_ptr<TabEntry>>; | 
|  | TabEntryMap tab_entries_; | 
|  | }; | 
|  |  | 
|  | }  // namespace extensions | 
|  |  | 
|  | #endif  // CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_ANDROID_H_ |