blob: 80491336dfa56303a776140d64146f9b043c3f75 [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.
#ifndef CHROME_BROWSER_APPS_BROWSER_INSTANCE_BROWSER_APP_INSTANCE_TRACKER_H_
#define CHROME_BROWSER_APPS_BROWSER_INSTANCE_BROWSER_APP_INSTANCE_TRACKER_H_
#include <map>
#include <memory>
#include <set>
#include "base/check.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_multi_source_observation.h"
#include "base/unguessable_token.h"
#include "chrome/browser/apps/browser_instance/browser_app_instance.h"
#include "chrome/browser/apps/browser_instance/browser_app_instance_map.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/browser_tab_strip_tracker.h"
#include "chrome/browser/ui/browser_tab_strip_tracker_delegate.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "components/app_constants/constants.h"
#include "components/services/app_service/public/cpp/app_registry_cache.h"
#include "content/public/browser/web_contents.h"
class Browser;
class Profile;
namespace apps {
class BrowserAppInstanceObserver;
// BrowserAppInstanceTracker monitors changes to Browsers, TabStripModels and
// browsers' native window activation to maintain a list of running apps and
// notify its registered observers of any changes:
// - apps running in WebContents (web apps, hosted apps, V1 packaged apps)
// - browser instances (registered with app ID |app_constants::kChromeAppId|).
class BrowserAppInstanceTracker : public TabStripModelObserver,
public BrowserTabStripTrackerDelegate,
public AppRegistryCache::Observer,
public BrowserListObserver {
public:
BrowserAppInstanceTracker(Profile* profile,
AppRegistryCache& app_registry_cache);
~BrowserAppInstanceTracker() override;
BrowserAppInstanceTracker(const BrowserAppInstanceTracker&) = delete;
BrowserAppInstanceTracker& operator=(const BrowserAppInstanceTracker&) =
delete;
// Get an app instance associated with |contents|. It will return either an
// app instance associated with this tab, or an app instance associated with a
// browser containing this tab (for app windows and tabs in tabbed app
// windows). Returns null if no app is found.
const BrowserAppInstance* GetAppInstance(
content::WebContents* contents) const;
// Get a window app instance associated with |browser|. Returns null if no app
// is found.
const BrowserAppInstance* GetAppInstance(Browser* browser) const;
// Get Chrome instance running in |browser|. Returns null if not found.
const BrowserWindowInstance* GetBrowserWindowInstance(Browser* browser) const;
// Activate the given instance within its tabstrip. If the instance lives in
// its own window, this will have no effect.
void ActivateTabInstance(base::UnguessableToken id);
// Stop all running instances of an app. The app's associated windows/tabs
// will be closed.
void StopInstancesOfApp(const std::string& app_id);
void AddObserver(BrowserAppInstanceObserver* observer) {
observers_.AddObserver(observer);
}
void RemoveObserver(BrowserAppInstanceObserver* observer) {
observers_.RemoveObserver(observer);
}
// TabStripModelObserver overrides:
void OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) override;
// BrowserTabStripTrackerDelegate overrides:
bool ShouldTrackBrowser(BrowserWindowInterface* browser) override;
// BrowserListObserver overrides:
void OnBrowserAdded(Browser* browser) override;
void OnBrowserRemoved(Browser* browser) override;
// apps::AppRegistryCache::Observer:
void OnAppUpdate(const AppUpdate& update) override;
void OnAppRegistryCacheWillBeDestroyed(AppRegistryCache* cache) override;
// Remove `browser` from internal tracking.
void RemoveBrowserForTesting(Browser* browser);
private:
class WebContentsObserver;
friend class BrowserAppInstanceRegistry;
// Called by TabStripModelChanged().
void OnTabStripModelChangeInsert(Browser* browser,
const TabStripModelChange::Insert& insert,
const TabStripSelectionChange& selection);
void OnTabStripModelChangeRemove(Browser* browser,
const TabStripModelChange::Remove& remove,
const TabStripSelectionChange& selection);
void OnTabStripModelChangeReplace(
Browser* browser,
const TabStripModelChange::Replace& replace);
void OnTabStripModelChangeSelection(Browser* browser,
const TabStripSelectionChange& selection);
// Called by OnTabStripModelChange* functions.
virtual void OnBrowserFirstTabAttached(Browser* browser);
virtual void OnBrowserLastTabDetached(Browser* browser);
void OnTabCreated(Browser* browser, content::WebContents* contents);
void OnTabAttached(Browser* browser, content::WebContents* contents);
void OnTabUpdated(Browser* browser, content::WebContents* contents);
void OnTabClosing(Browser* browser, content::WebContents* contents);
// Called by |BrowserAppInstanceTracker::WebContentsObserver|.
void OnWebContentsUpdated(content::WebContents* contents);
// App tab instance lifecycle
// Creates an app tab instance for the app running in |contents|.
void CreateAppTabInstance(std::string app_id,
Browser* browser,
content::WebContents* contents);
// Updates the app instance with the new attributes and notifies observers, if
// it was updated.
void MaybeUpdateAppTabInstance(BrowserAppInstance& instance,
Browser* browser,
content::WebContents* contents);
// Removes the app tab instance, if it exists, and notifies observers.
void RemoveAppTabInstanceIfExists(content::WebContents* contents);
// App window instance lifecycle
// Creates an app window instance for the app running in |browser|.
void CreateAppWindowInstance(std::string app_id, Browser* browser);
// Updates the app instance with the new attributes and notifies observers, if
// it was updated.
void MaybeUpdateAppWindowInstance(BrowserAppInstance& instance,
Browser* browser);
// Removes the app window instance, if it exists, and notifies observers.
void RemoveAppWindowInstanceIfExists(Browser* browser);
// Browser window instance lifecycle
// Creates an app instance for a Chrome browser window.
void CreateBrowserWindowInstance(Browser* browser);
// Removes the browser instance, if it exists, and notifies observers.
void RemoveBrowserWindowInstanceIfExists(Browser* browser);
// Virtual to override in tests.
virtual base::UnguessableToken GenerateId() const;
bool IsBrowserTracked(Browser* browser) const;
const raw_ptr<Profile, DanglingUntriaged> profile_;
std::map<content::WebContents*, std::unique_ptr<WebContentsObserver>>
webcontents_to_observer_map_;
// A set of observed browsers: browsers where at least one tab has been added.
// Events for all other browsers are filtered out.
std::set<raw_ptr<Browser, SetExperimental>> tracked_browsers_;
BrowserTabStripTracker browser_tab_strip_tracker_;
#if DCHECK_IS_ON()
// Tabs that are removed from one browser and are getting reinserted into
// another.
std::set<raw_ptr<content::WebContents, SetExperimental>> tabs_in_transit_;
#endif
// App instances running in tabs.
BrowserAppInstanceMap<content::WebContents*, BrowserAppInstance>
app_tab_instances_;
// App instances running in windows.
BrowserAppInstanceMap<Browser*, BrowserAppInstance> app_window_instances_;
// Chrome browser windows.
BrowserAppInstanceMap<Browser*, BrowserWindowInstance> window_instances_;
base::ScopedObservation<apps::AppRegistryCache,
apps::AppRegistryCache::Observer>
app_registry_cache_observer_{this};
base::ObserverList<BrowserAppInstanceObserver, true>::Unchecked observers_;
};
} // namespace apps
#endif // CHROME_BROWSER_APPS_BROWSER_INSTANCE_BROWSER_APP_INSTANCE_TRACKER_H_