blob: 0b03bebee83ef8b576bec3a45d40b4a6d6d77cb9 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_APPS_APP_SERVICE_BROWSER_APP_INSTANCE_TRACKER_H_
#define CHROME_BROWSER_APPS_APP_SERVICE_BROWSER_APP_INSTANCE_TRACKER_H_
#include <map>
#include <memory>
#include <set>
#include "base/check.h"
#include "base/observer_list.h"
#include "base/scoped_multi_source_observation.h"
#include "base/unguessable_token.h"
#include "chrome/browser/apps/app_service/browser_app_instance.h"
#include "chrome/browser/apps/app_service/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/services/app_service/public/cpp/app_registry_cache.h"
#include "content/public/browser/web_contents.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/wm/public/activation_change_observer.h"
#include "ui/wm/public/activation_client.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 |extension_misc::kChromeAppId|).
class BrowserAppInstanceTracker : public TabStripModelObserver,
public BrowserTabStripTrackerDelegate,
public wm::ActivationChangeObserver,
public AppRegistryCache::Observer,
public BrowserListObserver {
public:
BrowserAppInstanceTracker(Profile* profile,
AppRegistryCache& app_registry_cache);
~BrowserAppInstanceTracker() override;
BrowserAppInstanceTracker(const BrowserAppInstanceTracker&) = delete;
BrowserAppInstanceTracker& operator=(const BrowserAppInstanceTracker&) =
delete;
// A factory method to make the creation of the tracker optional to keep it
// behind a flag.
// TODO(crbug.com/1203992): Remove this when the
// |kBrowserAppInstanceTracking| flag is removed.
static std::unique_ptr<BrowserAppInstanceTracker> Create(
Profile* profile,
AppRegistryCache& app_registry_cache);
// Get all instances by app ID. Returns a set of unowned pointers.
std::set<const BrowserAppInstance*> GetAppInstancesByAppId(
const std::string& app_id) const;
// Get all instances by app ID. Returns a set of unowned pointers.
std::set<const BrowserWindowInstance*> GetBrowserWindowInstances() const;
// Checks if at least one instance of the app is running.
bool IsAppRunning(const std::string& app_id) const;
// Checks if at least one instance of the app is running.
bool IsBrowserRunning() const;
// Get app instance running in a |contents|. Returns null if no app is found.
const BrowserAppInstance* GetAppInstance(
content::WebContents* contents) const;
// Get app instance running in a |contents|. Returns null if no app is found.
const BrowserAppInstance* GetAppInstanceById(base::UnguessableToken id) const;
// Get Chrome instance running in |browser|. Returns null if not found.
const BrowserWindowInstance* GetWindowInstance(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;
bool ShouldTrackBrowser(Browser* browser) override;
// wm::ActivationChangeObserver overrides:
void OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) 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;
private:
class WebContentsObserver;
// 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.
void OnBrowserFirstTabAttached(Browser* browser);
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);
// Called on browser window changes. Sends update events for all open tabs.
void OnBrowserWindowUpdated(Browser* browser);
// Creates an app instance for the app running in |WebContents|. Handles both
// apps in tabs and windows.
void CreateAppInstance(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 MaybeUpdateAppInstance(BrowserAppInstance& instance,
Browser* browser,
content::WebContents* contents);
// Removes the app instance, if it exists, and notifies observers.
void RemoveAppInstanceIfExists(content::WebContents* contents);
// Creates an app instance for a Chrome browser window.
void CreateWindowInstance(Browser* browser);
// Updates the browser instance with the new attributes and notifies
// observers, if it was updated.
void MaybeUpdateWindowInstance(BrowserWindowInstance& instance,
Browser* browser);
// Removes the browser instance, if it exists, and notifies observers.
void RemoveWindowInstanceIfExists(Browser* browser);
// Virtual to override in tests.
virtual base::UnguessableToken GenerateId() const;
bool IsBrowserTracked(Browser* browser) const;
bool IsActivationClientTracked(wm::ActivationClient* client) const;
Profile* 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<Browser*> tracked_browsers_;
// A set of observed activation clients for all browser's windows.
base::ScopedMultiSourceObservation<wm::ActivationClient,
wm::ActivationChangeObserver>
activation_client_observations_{this};
BrowserTabStripTracker browser_tab_strip_tracker_;
#if DCHECK_IS_ON()
// Tabs that are removed from one browser and are getting reinserted into
// another.
std::set<content::WebContents*> tabs_in_transit_;
#endif
// A set of all apps running in either tabs or windows.
BrowserAppInstanceMap<content::WebContents*, BrowserAppInstance>
app_instances_;
// Chrome browser windows.
BrowserAppInstanceMap<Browser*, BrowserWindowInstance> window_instances_;
base::ObserverList<BrowserAppInstanceObserver, true>::Unchecked observers_;
};
} // namespace apps
#endif // CHROME_BROWSER_APPS_APP_SERVICE_BROWSER_APP_INSTANCE_TRACKER_H_