| // Copyright 2022 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_METRICS_WEBSITE_METRICS_H_ |
| #define CHROME_BROWSER_APPS_APP_SERVICE_METRICS_WEBSITE_METRICS_H_ |
| |
| #include <map> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/scoped_multi_source_observation.h" |
| #include "base/scoped_observation.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser_list_observer.h" |
| #include "chrome/browser/ui/browser_tab_strip_tracker.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" |
| #include "components/history/core/browser/history_service.h" |
| #include "components/history/core/browser/history_service_observer.h" |
| #include "components/webapps/browser/banners/app_banner_manager.h" |
| #include "content/public/browser/page.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "ui/wm/public/activation_change_observer.h" |
| #include "ui/wm/public/activation_client.h" |
| #include "url/gurl.h" |
| |
| class Browser; |
| class Profile; |
| |
| namespace apps { |
| |
| class WebsiteMetricsBrowserTest; |
| class TestWebsiteMetrics; |
| |
| // This is used for logging, so do not remove or reorder existing entries. |
| enum class UrlContent { |
| kUnknown = 0, |
| kFullUrl = 1, |
| kScope = 2, |
| |
| // Add any new values above this one, and update kMaxValue to the highest |
| // enumerator value. |
| kMaxValue = kScope, |
| }; |
| |
| extern const char kWebsiteUsageTime[]; |
| extern const char kRunningTimeKey[]; |
| extern const char kUrlContentKey[]; |
| extern const char kPromotableKey[]; |
| |
| // WebsiteMetrics monitors creation/deletion of Browser and its |
| // TabStripModel to record the website usage time metrics. |
| class WebsiteMetrics : public BrowserListObserver, |
| public TabStripModelObserver, |
| public wm::ActivationChangeObserver, |
| public history::HistoryServiceObserver { |
| public: |
| explicit WebsiteMetrics(Profile* profile); |
| |
| WebsiteMetrics(const WebsiteMetrics&) = delete; |
| WebsiteMetrics& operator=(const WebsiteMetrics&) = delete; |
| |
| ~WebsiteMetrics() override; |
| |
| // BrowserListObserver overrides: |
| void OnBrowserAdded(Browser* browser) override; |
| |
| // TabStripModelObserver overrides: |
| void OnTabStripModelChanged( |
| TabStripModel* tab_strip_model, |
| const TabStripModelChange& change, |
| const TabStripSelectionChange& selection) override; |
| |
| // wm::ActivationChangeObserver overrides: |
| void OnWindowActivated(ActivationReason reason, |
| aura::Window* gained_active, |
| aura::Window* lost_active) override; |
| |
| // history::HistoryServiceObserver: |
| void OnURLsDeleted(history::HistoryService* history_service, |
| const history::DeletionInfo& deletion_info) override; |
| void HistoryServiceBeingDeleted( |
| history::HistoryService* history_service) override; |
| |
| // Save the usage time records to the local user perf. |
| void OnFiveMinutes(); |
| |
| // Records the usage time UKM each 2 hours. |
| void OnTwoHours(); |
| |
| private: |
| friend class WebsiteMetricsBrowserTest; |
| friend class TestWebsiteMetrics; |
| |
| // This class monitors the activated WebContent for the activated browser |
| // window and notifies a navigation to the WebsiteMetrics. |
| class ActiveTabWebContentsObserver |
| : public content::WebContentsObserver, |
| public webapps::AppBannerManager::Observer { |
| public: |
| ActiveTabWebContentsObserver(content::WebContents* contents, |
| WebsiteMetrics* owner); |
| |
| ActiveTabWebContentsObserver(const ActiveTabWebContentsObserver&) = delete; |
| ActiveTabWebContentsObserver& operator=( |
| const ActiveTabWebContentsObserver&) = delete; |
| |
| ~ActiveTabWebContentsObserver() override; |
| |
| // content::WebContentsObserver |
| void PrimaryPageChanged(content::Page& page) override; |
| void WebContentsDestroyed() override; |
| |
| // webapps::AppBannerManager::Observer: |
| void OnInstallableWebAppStatusUpdated() override; |
| |
| private: |
| WebsiteMetrics* owner_; |
| base::ScopedObservation<webapps::AppBannerManager, |
| webapps::AppBannerManager::Observer> |
| app_banner_manager_observer_{this}; |
| }; |
| |
| struct UrlInfo { |
| base::TimeTicks start_time; |
| base::TimeDelta running_time; |
| UrlContent url_content = UrlContent::kUnknown; |
| bool is_activated = false; |
| bool promotable = false; |
| |
| // Converts the struct UsageTime to base::Value, e.g.: |
| // { |
| // "time": "3600", |
| // "url_content": "scope", |
| // "promotable": "false", |
| // } |
| base::Value ConvertToValue() const; |
| }; |
| |
| void OnTabStripModelChangeInsert(TabStripModel* tab_strip_model, |
| const TabStripModelChange::Insert& insert, |
| const TabStripSelectionChange& selection); |
| void OnTabStripModelChangeRemove(aura::Window* window, |
| TabStripModel* tab_strip_model, |
| const TabStripModelChange::Remove& remove, |
| const TabStripSelectionChange& selection); |
| void OnTabStripModelChangeReplace( |
| const TabStripModelChange::Replace& replace); |
| void OnActiveTabChanged(aura::Window* window, |
| content::WebContents* old_contents, |
| content::WebContents* new_contents); |
| void OnTabClosed(content::WebContents* web_contents); |
| |
| // Called by |WebsiteMetrics::ActiveTabWebContentsObserver|. |
| virtual void OnWebContentsUpdated(content::WebContents* web_contents); |
| virtual void OnInstallableWebAppStatusUpdated( |
| content::WebContents* web_contents); |
| |
| // Adds the url info to `url_infos_`. |
| void AddUrlInfo(const GURL& url, |
| const base::TimeTicks& start_time, |
| UrlContent url_content, |
| bool is_activated, |
| bool promotable); |
| |
| // Modifies `old_url` to `new_url` in `url_infos_`, when the website manifest |
| // is updated. |
| void UpdateUrlInfo(const GURL& old_url, |
| const GURL& new_url, |
| UrlContent url_content, |
| bool is_activated, |
| bool promotable); |
| |
| void SetWindowActivated(aura::Window* window); |
| |
| void SetWindowInActivated(aura::Window* window); |
| |
| void SetTabActivated(content::WebContents* web_contents); |
| |
| void SetTabInActivated(content::WebContents* web_contents); |
| |
| // Saves the website usage time in `url_infos_` to the user pref each 5 |
| // minutes. |
| void SaveUsageTime(); |
| |
| const raw_ptr<Profile> profile_; |
| |
| BrowserTabStripTracker browser_tab_strip_tracker_; |
| |
| // The map from the window to the active tab contents. |
| base::flat_map<aura::Window*, content::WebContents*> window_to_web_contents_; |
| |
| std::map<content::WebContents*, std::unique_ptr<ActiveTabWebContentsObserver>> |
| webcontents_to_observer_map_; |
| |
| // The map from the web_contents to the ukm key url. When the url for web |
| // contents is updated in OnWebContentsUpdated, we can get the previous url |
| // from this map to calculate the usage time for the previous url. |
| // |
| // If the url is used for an app, it won't be added to the map, because the |
| // app metrics can record the usage time metrics. |
| // |
| // If the website has a manifest, we might use the scope or the start url as |
| // the ukm key url. Otherwise, the visible url is used as the ukm key url. |
| std::map<content::WebContents*, GURL> webcontents_to_ukm_key_; |
| |
| // Saves the usage info for the activated urls in activated windows for the |
| // UKM records. `url_infos_` is cleared after recording the UKM each 2 hours. |
| std::map<GURL, UrlInfo> url_infos_; |
| |
| // A set of observed activation clients for all browser's windows. |
| base::ScopedMultiSourceObservation<wm::ActivationClient, |
| wm::ActivationChangeObserver> |
| activation_client_observations_{this}; |
| |
| base::ScopedObservation<history::HistoryService, |
| history::HistoryServiceObserver> |
| history_observation_{this}; |
| |
| base::WeakPtrFactory<WebsiteMetrics> weak_factory_{this}; |
| }; |
| |
| } // namespace apps |
| |
| #endif // CHROME_BROWSER_APPS_APP_SERVICE_METRICS_WEBSITE_METRICS_H_ |