// Copyright 2017 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.

#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"

#include <limits>

#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/rand_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/resource_coordinator/tab_manager_features.h"
#include "chrome/browser/resource_coordinator/tab_metrics_logger.h"
#include "chrome/browser/resource_coordinator/tab_ranker/mru_features.h"
#include "chrome/browser/resource_coordinator/tab_ranker/tab_features.h"
#include "chrome/browser/resource_coordinator/tab_ranker/window_features.h"
#include "chrome/browser/resource_coordinator/time.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/window_activity_watcher.h"
#include "components/ukm/content/source_url_recorder.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/platform/web_input_event.h"

// Use a 1-day max for tab visibility histograms since it's not uncommon to keep
// a tab in the same visibility state for a very long time (see Tab.VisibleTime
// which has 5% of samples in the overflow bucket with a 1-hour max).
#define UMA_TAB_VISIBILITY_HISTOGRAM(visibility, sample)           \
  UMA_HISTOGRAM_CUSTOM_TIMES("Tab.Visibility." visibility, sample, \
                             base::TimeDelta::FromMilliseconds(1), \
                             base::TimeDelta::FromDays(1), 50)

namespace resource_coordinator {
namespace {

// Returns an int64_t number as label_id or query_id. The number is generated
// incrementally from 1.
int64_t NewInt64ForLabelIdOrQueryId() {
  static int64_t id = 0;
  return ++id;
}

}  // namespace

// Per-WebContents helper class that observes its WebContents, notifying
// TabActivityWatcher when interesting events occur. Also provides
// per-WebContents data that TabActivityWatcher uses to log the tab.
class TabActivityWatcher::WebContentsData
    : public content::WebContentsObserver,
      public content::WebContentsUserData<WebContentsData>,
      public content::RenderWidgetHost::InputEventObserver {
 public:
  ~WebContentsData() override = default;

  // Calculates the tab reactivation score for a background tab. Returns nullopt
  // if the score could not be calculated, e.g. because the tab is in the
  // foreground.
  base::Optional<float> CalculateReactivationScore() {
    if (web_contents()->IsBeingDestroyed() || backgrounded_time_.is_null())
      return base::nullopt;

    // Only Scores Oldest N tabs (based on least recently used index calculated
    // as mru.total - mru.index - 1).
    const auto mru = GetMRUFeatures();
    const int lru_index = mru.total - mru.index - 1;

    // If the least recently used index is greater than or equal to N, which
    // means the tab is not in the oldest N list, we should simply skip it.
    // The N is defaulted as kMaxInt so that all tabs are scored.
    if (lru_index >= GetNumOldestTabsToScoreWithTabRanker())
      return base::nullopt;

    base::Optional<tab_ranker::TabFeatures> tab = GetTabFeatures(mru);
    if (!tab.has_value())
      return base::nullopt;

    float score = 0.0f;
    const tab_ranker::TabRankerResult result =
        TabActivityWatcher::GetInstance()->predictor_.ScoreTab(tab.value(),
                                                               &score);
    if (result == tab_ranker::TabRankerResult::kSuccess)
      return score;
    return base::nullopt;
  }

  // Call when the associated WebContents has been replaced.
  void WasReplaced() { was_replaced_ = true; }

  // Call when the associated WebContents has replaced the WebContents of
  // another tab. Copies info from the other WebContentsData so future events
  // can be logged consistently.
  void DidReplace(const WebContentsData& replaced_tab) {
    // Copy creation and foregrounded times to retain the replaced tab's MRU
    // position.
    creation_time_ = replaced_tab.creation_time_;
    foregrounded_time_ = replaced_tab.foregrounded_time_;

    // Copy background status so ForegroundOrClosed can potentially be logged.
    backgrounded_time_ = replaced_tab.backgrounded_time_;

    // Copy the replaced tab's stats.
    tab_metrics_.page_metrics = replaced_tab.tab_metrics_.page_metrics;
    tab_metrics_.page_transition = replaced_tab.tab_metrics_.page_transition;

    // Record previous ukm_source_id from the |replaced_tab|.
    previous_ukm_source_id_ = replaced_tab.ukm_source_id_;

    // Copy the replaced label_id_.
    label_id_ = replaced_tab.label_id_;
  }

  // Call when the WebContents is detached from its tab. If the tab is later
  // re-inserted elsewhere, we use the state it had before being detached.
  void TabDetached() { is_detached_ = true; }

  // Call when the tab is inserted into a tab strip to update state.
  void TabInserted(bool foreground) {
    if (is_detached_) {
      is_detached_ = false;

      // Dragged tabs are normally inserted into their new tab strip in the
      // "background", then "activated", even though the user perceives the tab
      // staying active the whole time. So don't update |background_time_| here.
      //
      // TODO(michaelpg): If a background tab is dragged (as part of a group)
      // and inserted, it may be treated as being foregrounded (depending on tab
      // order). This is a small edge case, but can be fixed by the plan to
      // merge the ForegroundedOrClosed and TabMetrics events.
      return;
    }

    if (foreground) {
      foregrounded_time_ = NowTicks();
    } else {
      // This is a new tab that was opened in the background.
      backgrounded_time_ = NowTicks();
    }
  }

  // Logs TabMetrics for the tab if it is considered to be backgrounded.
  void LogTabIfBackgrounded() {
    if (backgrounded_time_.is_null() || DisableBackgroundLogWithTabRanker())
      return;

    base::Optional<tab_ranker::TabFeatures> tab = GetTabFeatures();
    if (tab.has_value()) {
      // Background time logging always logged with label_id == 0, since we
      // only use label_id for query time logging for now.
      TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabMetrics(
          ukm_source_id_, tab.value(), web_contents(), 0);
    }
  }

  // Logs current TabFeatures; skips if current tab is foregrounded.
  void LogCurrentTabFeatures() {
    if (backgrounded_time_.is_null())
      return;
    const base::Optional<tab_ranker::TabFeatures> tab =
        GetTabFeatures(mru_features_);
    if (!tab.has_value())
      return;

    // A new label_id_ is generated for this query.
    // The same label_id_ will be logged with ForegroundedOrClosed event later
    // on so that TabFeatures can be paired with ForegroundedOrClosed.
    label_id_ = NewInt64ForLabelIdOrQueryId();

    TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabMetrics(
        ukm_source_id_, tab.value(), web_contents(), label_id_);
  }

  // Sets foregrounded_time_ to NowTicks() so this becomes the
  // most-recently-used tab.
  void TabWindowActivated() { foregrounded_time_ = NowTicks(); }

 private:
  friend class content::WebContentsUserData<WebContentsData>;
  friend class TabActivityWatcher;

  explicit WebContentsData(content::WebContents* web_contents)
      : WebContentsObserver(web_contents) {
    DCHECK(!web_contents->GetBrowserContext()->IsOffTheRecord());
    tab_metrics_.web_contents = web_contents;
    web_contents->GetRenderViewHost()->GetWidget()->AddInputEventObserver(this);

    creation_time_ = NowTicks();

    // A navigation may already have completed if this is a replacement tab.
    ukm_source_id_ = ukm::GetSourceIdForWebContentsDocument(web_contents);

    // When a tab is discarded, a new null_web_contents will be created (with
    // WasDiscarded set as true) applied as a replacement of the discarded tab.
    // We want to record this discarded state for later logging.
    discarded_since_backgrounded_ = web_contents->WasDiscarded();
  }

  void WasHidden() {
    // The tab may not be in the tabstrip if it's being moved or replaced.
    Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
    if (!browser)
      return;

    DCHECK(!browser->tab_strip_model()->closing_all());

    if (browser->tab_strip_model()->GetActiveWebContents() == web_contents() &&
        !browser->window()->IsMinimized()) {
      // The active tab is considered to be in the foreground unless its window
      // is minimized. It might still get hidden, e.g. when the browser is about
      // to close, but that shouldn't count as a backgrounded event.
      //
      // TODO(michaelpg): On Mac, hiding the application (e.g. via Cmd+H) should
      // log tabs as backgrounded. Check NSApplication's isHidden property.
      return;
    }

    backgrounded_time_ = NowTicks();
    discarded_since_backgrounded_ = false;
    LogTabIfBackgrounded();
  }

  void WasShown() {
    if (backgrounded_time_.is_null())
      return;

    Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
    if (browser && browser->tab_strip_model()->closing_all())
      return;

    // Log the event before updating times.
    LogForegroundedOrClosedMetrics(true /* is_foregrounded */);

    backgrounded_time_ = base::TimeTicks();
    foregrounded_time_ = NowTicks();
    creation_time_ = NowTicks();

    tab_metrics_.page_metrics.num_reactivations++;
  }

  // content::WebContentsObserver:
  void RenderViewHostChanged(content::RenderViewHost* old_host,
                             content::RenderViewHost* new_host) override {
    if (old_host != nullptr)
      old_host->GetWidget()->RemoveInputEventObserver(this);
    new_host->GetWidget()->AddInputEventObserver(this);
  }

  void DidFinishNavigation(
      content::NavigationHandle* navigation_handle) override {
    if (!navigation_handle->HasCommitted() ||
        !navigation_handle->IsInMainFrame() ||
        navigation_handle->IsSameDocument()) {
      return;
    }

    // Use the same SourceId that SourceUrlRecorderWebContentsObserver populates
    // and updates.
    ukm::SourceId new_source_id = ukm::ConvertToSourceId(
        navigation_handle->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID);
    DCHECK_NE(new_source_id, ukm_source_id_)
        << "Expected a unique Source ID for the navigation";
    ukm_source_id_ = new_source_id;

    // Update navigation time for UKM reporting.
    navigation_time_ = navigation_handle->NavigationStart();

    // Reset the per-page data.
    tab_metrics_.page_metrics = {};

    // Update navigation info.
    tab_metrics_.page_transition = navigation_handle->GetPageTransition();
  }

  // Logs metrics for the tab when it stops loading instead of immediately
  // after a navigation commits, so we can have some idea of its status and
  // contents.
  void DidStopLoading() override {
    // Ignore load events in foreground tabs. The tab state of a foreground tab
    // will be logged if/when it is backgrounded.
    LogTabIfBackgrounded();
  }

  void OnVisibilityChanged(content::Visibility visibility) override {
    // Record Tab.Visibility.* histogram and do associated bookkeeping.
    // Recording is done at every visibility state change rather than just when
    // the WebContents is destroyed to reduce data loss on session end.
    RecordVisibilityHistogram(visibility);

    // Record background tab UKMs and do associated bookkepping.
    if (!web_contents()->IsBeingDestroyed()) {
      // TODO(michaelpg): Consider treating occluded tabs as hidden.
      if (visibility == content::Visibility::HIDDEN) {
        WasHidden();
      } else {
        WasShown();
      }
    }
  }

  void RecordVisibilityHistogram(content::Visibility new_visibility) {
    const base::TimeTicks now = NowTicks();
    const base::TimeDelta duration = now - last_visibility_change_time_;
    switch (visibility_) {
      case content::Visibility::VISIBLE: {
        UMA_TAB_VISIBILITY_HISTOGRAM("Visible", duration);
        break;
      }

      case content::Visibility::OCCLUDED: {
        UMA_TAB_VISIBILITY_HISTOGRAM("Occluded", duration);
        break;
      }

      case content::Visibility::HIDDEN: {
        UMA_TAB_VISIBILITY_HISTOGRAM("Hidden", duration);
        break;
      }
    }

    visibility_ = new_visibility;
    last_visibility_change_time_ = now;
  }

  void WebContentsDestroyed() override {
    RecordVisibilityHistogram(visibility_);

    if (was_replaced_)
      return;

    // Log necessary metrics.
    TabActivityWatcher::GetInstance()->OnTabClosed(this);
  }

  // content::RenderWidgetHost::InputEventObserver:
  void OnInputEvent(const blink::WebInputEvent& event) override {
    if (blink::WebInputEvent::IsMouseEventType(event.GetType()))
      tab_metrics_.page_metrics.mouse_event_count++;
    else if (blink::WebInputEvent::IsKeyboardEventType(event.GetType()))
      tab_metrics_.page_metrics.key_event_count++;
    else if (blink::WebInputEvent::IsTouchEventType(event.GetType()))
      tab_metrics_.page_metrics.touch_event_count++;
  }

  // Iterates through tabstrips to determine the index of |contents| in
  // most-recently-used order out of all non-incognito tabs.
  // Linear in the number of tabs (most users have <10 tabs open).
  tab_ranker::MRUFeatures GetMRUFeatures() {
    const auto& all_closing_tabs =
        TabActivityWatcher::GetInstance()->all_closing_tabs_;
    // If in closing_all mode, directly returns current |mru_features_|.
    if (all_closing_tabs.find(this) != all_closing_tabs.end()) {
      return mru_features_;
    }

    // If not in closing_all mode, calculate |mru_features_|.
    mru_features_.index = 0;
    mru_features_.total = 0;
    for (Browser* browser : *BrowserList::GetInstance()) {
      // Ignore incognito browsers.
      if (browser->profile()->IsOffTheRecord())
        continue;

      int count = browser->tab_strip_model()->count();
      mru_features_.total += count;

      // Increment the MRU index for each WebContents that was foregrounded more
      // recently than this one.
      for (int i = 0; i < count; i++) {
        auto* other = WebContentsData::FromWebContents(
            browser->tab_strip_model()->GetWebContentsAt(i));
        if (!other || this == other)
          continue;

        if (!MoreRecentlyUsed(this, other))
          mru_features_.index++;
      }
    }
    return mru_features_;
  }

  // Returns whether |webcontents_a| is more recently used than |webcontents_b|.
  // A webcontents is more recently used iff it has larger (later)
  // |foregrounded_time_|; or |creation_time_| if they were never foregrounded.
  static bool MoreRecentlyUsed(
      TabActivityWatcher::WebContentsData* webcontents_a,
      TabActivityWatcher::WebContentsData* const webcontents_b) {
    return webcontents_a->foregrounded_time_ >
               webcontents_b->foregrounded_time_ ||
           (webcontents_a->foregrounded_time_ ==
                webcontents_b->foregrounded_time_ &&
            webcontents_a->creation_time_ > webcontents_b->creation_time_);
  }

  // Returns the tabfeatures of current tab by combining TabMetrics,
  // WindowFeatures and MRUFeatures.
  base::Optional<tab_ranker::TabFeatures> GetTabFeatures(
      const tab_ranker::MRUFeatures& mru = tab_ranker::MRUFeatures()) {
    const Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
    if (!browser)
      return base::nullopt;

    // For tab features.
    tab_ranker::TabFeatures tab = TabMetricsLogger::GetTabFeatures(
        browser, tab_metrics_, NowTicks() - backgrounded_time_);

    // For window features.
    tab_ranker::WindowFeatures window =
        WindowActivityWatcher::CreateWindowFeatures(browser);
    tab.window_is_active = window.is_active;
    tab.window_show_state = window.show_state;
    tab.window_tab_count = window.tab_count;
    tab.window_type = window.type;

    // For mru features.
    tab.mru_index = mru.index;
    tab.total_tab_count = mru.total;
    return tab;
  }

  // Collect current ForegroundedOrClosedMetrics and send to ukm.
  void LogForegroundedOrClosedMetrics(bool is_foregrounded) {
    TabMetricsLogger::ForegroundedOrClosedMetrics metrics;
    metrics.is_foregrounded = is_foregrounded;
    metrics.is_discarded = discarded_since_backgrounded_;
    metrics.time_from_backgrounded =
        (NowTicks() - backgrounded_time_).InMilliseconds();
    const auto mru = GetMRUFeatures();
    metrics.mru_index = mru.index;
    metrics.total_tab_count = mru.total;
    metrics.label_id = label_id_;

    const ukm::SourceId source_id = discarded_since_backgrounded_
                                        ? previous_ukm_source_id_
                                        : ukm_source_id_;
    TabActivityWatcher::GetInstance()
        ->tab_metrics_logger_->LogForegroundedOrClosedMetrics(source_id,
                                                              metrics);
    // label_id_ is reset whenever a label is logged.
    // A new label_id_ is generated when a query happens inside
    // CalculateReactivationScore, after that this ForegroundedOrClosed logging
    // can happen many times (tabs may get backgrounded and reactivated several
    // times). In such cases, we only count the first time as the true label,
    // the rest are considered to be query time logging irrelevant, for which we
    // log with label_id == 0.
    label_id_ = 0;
  }

  // Updated when a navigation is finished.
  ukm::SourceId ukm_source_id_ = 0;

  // Recorded when a WebContents is replaced by another.
  ukm::SourceId previous_ukm_source_id_ = 0;

  // When the tab was created.
  base::TimeTicks creation_time_;

  // The most recent time the tab became backgrounded. This happens when a
  // different tab in the tabstrip is activated or the tab's window is hidden.
  base::TimeTicks backgrounded_time_;

  // The most recent time the tab became foregrounded. This happens when the
  // tab becomes the active tab in the tabstrip or when the active tab's window
  // is activated.
  base::TimeTicks foregrounded_time_;

  // The last navigation time associated with this tab.
  base::TimeTicks navigation_time_;

  // Stores current stats for the tab.
  TabMetricsLogger::TabMetrics tab_metrics_;

  // Set to true when the WebContents has been detached from its tab.
  bool is_detached_ = false;

  // If true, future events such as the tab being destroyed won't be logged.
  bool was_replaced_ = false;

  // Current tab visibility.
  content::Visibility visibility_ = web_contents()->GetVisibility();

  // The last time at which |visibility_| changed.
  base::TimeTicks last_visibility_change_time_ = NowTicks();

  // MRUFeatures of this WebContents, updated only before ForegroundedOrClosed
  // event is logged.
  tab_ranker::MRUFeatures mru_features_;

  // Whether this tab is currently in discarded state.
  bool discarded_since_backgrounded_ = false;

  // An int64 random label to pair TabFeatures with ForegroundedOrClosed event.
  int64_t label_id_ = 0;

  WEB_CONTENTS_USER_DATA_KEY_DECL();

  DISALLOW_COPY_AND_ASSIGN(WebContentsData);
};

WEB_CONTENTS_USER_DATA_KEY_IMPL(TabActivityWatcher::WebContentsData)

TabActivityWatcher::TabActivityWatcher()
    : tab_metrics_logger_(std::make_unique<TabMetricsLogger>()),
      browser_tab_strip_tracker_(this, this, this) {
  browser_tab_strip_tracker_.Init();

  // TabMetrics UKMs reference WindowMetrics UKM entries, so ensure the
  // WindowActivityWatcher is initialized.
  WindowActivityWatcher::GetInstance();
}

TabActivityWatcher::~TabActivityWatcher() = default;

base::Optional<float> TabActivityWatcher::CalculateReactivationScore(
    content::WebContents* web_contents) {
  WebContentsData* web_contents_data =
      WebContentsData::FromWebContents(web_contents);
  if (!web_contents_data)
    return base::nullopt;
  return web_contents_data->CalculateReactivationScore();
}

void TabActivityWatcher::LogOldestNTabFeatures() {
  const int oldest_n_to_log = GetNumOldestTabsToLogWithTabRanker();
  if (oldest_n_to_log <= 0)
    return;

  // Set query_id so that all TabFeatures logged in this query can be joined.
  tab_metrics_logger_->set_query_id(NewInt64ForLabelIdOrQueryId());

  std::vector<WebContentsData*> web_contents_data = GetSortedWebContentsData();
  const int contents_data_size = web_contents_data.size();
  // Only log oldest n tabs which are tabs
  // from web_contents_data.size() - 1
  // to web_contents_data.size() - oldest_n_to_log.
  const int last_index_to_log =
      std::max(contents_data_size - oldest_n_to_log, 0);
  for (int i = contents_data_size - 1; i >= last_index_to_log; --i) {
    // Set correct mru_features_.
    web_contents_data[i]->mru_features_.index = i;
    web_contents_data[i]->mru_features_.total = contents_data_size;
    web_contents_data[i]->LogCurrentTabFeatures();
  }
}

void TabActivityWatcher::OnBrowserSetLastActive(Browser* browser) {
  if (browser->tab_strip_model()->closing_all())
    return;

  content::WebContents* active_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  if (!active_contents)
    return;

  // Don't assume the WebContentsData already exists in case activation happens
  // before the tabstrip is fully updated.
  WebContentsData* web_contents_data =
      WebContentsData::FromWebContents(active_contents);
  if (web_contents_data)
    web_contents_data->TabWindowActivated();
}

void TabActivityWatcher::OnTabStripModelChanged(
    TabStripModel* tab_strip_model,
    const TabStripModelChange& change,
    const TabStripSelectionChange& selection) {
  switch (change.type()) {
    case TabStripModelChange::kInserted: {
      for (const auto& delta : change.deltas()) {
        // Ensure the WebContentsData is created to observe this WebContents
        // since it may represent a newly created tab.
        WebContentsData::CreateForWebContents(delta.insert.contents);
        WebContentsData::FromWebContents(delta.insert.contents)
            ->TabInserted(selection.new_contents == delta.insert.contents);
      }
      break;
    }
    case TabStripModelChange::kRemoved: {
      for (const auto& delta : change.deltas())
        WebContentsData::FromWebContents(delta.remove.contents)->TabDetached();
      break;
    }
    case TabStripModelChange::kReplaced: {
      for (const auto& delta : change.deltas()) {
        WebContentsData* old_web_contents_data =
            WebContentsData::FromWebContents(delta.replace.old_contents);
        old_web_contents_data->WasReplaced();

        // Ensure the WebContentsData is created to observe this WebContents
        // since it likely hasn't been inserted into a tabstrip before.
        WebContentsData::CreateForWebContents(delta.replace.new_contents);

        WebContentsData::FromWebContents(delta.replace.new_contents)
            ->DidReplace(*old_web_contents_data);
      }
      break;
    }
    case TabStripModelChange::kMoved:
    case TabStripModelChange::kSelectionOnly:
      break;
  }
}

void TabActivityWatcher::TabPinnedStateChanged(TabStripModel* tab_strip_model,
                                               content::WebContents* contents,
                                               int index) {
  WebContentsData::FromWebContents(contents)->LogTabIfBackgrounded();
}

bool TabActivityWatcher::ShouldTrackBrowser(Browser* browser) {
  // Don't track incognito browsers. This is also enforced by UKM.
  // TODO(michaelpg): Keep counters for incognito browsers so we can score them
  // using the TabScorePredictor. We should be able to do this without logging
  // these values.
  return !browser->profile()->IsOffTheRecord();
}

void TabActivityWatcher::ResetForTesting() {
  tab_metrics_logger_ = std::make_unique<TabMetricsLogger>();
}

// static
TabActivityWatcher* TabActivityWatcher::GetInstance() {
  static base::NoDestructor<TabActivityWatcher> instance;
  return instance.get();
}

std::vector<TabActivityWatcher::WebContentsData*>
TabActivityWatcher::GetSortedWebContentsData() {
  // Put all web_contents_data into a vector.
  std::vector<WebContentsData*> web_contents_data;
  for (Browser* browser : *BrowserList::GetInstance()) {
    // Ignore incognito browsers.
    if (browser->profile()->IsOffTheRecord())
      continue;

    const int count = browser->tab_strip_model()->count();

    for (int i = 0; i < count; i++) {
      auto* const other = WebContentsData::FromWebContents(
          browser->tab_strip_model()->GetWebContentsAt(i));
      if (other)
        web_contents_data.push_back(other);
    }
  }

  // Sort all web_contents_data by MoreRecentlyUsed.
  std::sort(web_contents_data.begin(), web_contents_data.end(),
            WebContentsData::MoreRecentlyUsed);
  return web_contents_data;
}
// When a WillCloseAllTabs is invoked, all MRU index of that tab_strip_model
// is calculated and saved at that point.
void TabActivityWatcher::WillCloseAllTabs(TabStripModel* tab_strip_model) {
  if (tab_strip_model) {
    std::vector<WebContentsData*> web_contents_data =
        GetSortedWebContentsData();
    // Assign index for each web_contents_data.
    const std::size_t total_tabs = web_contents_data.size();
    for (std::size_t i = 0; i < total_tabs; ++i) {
      web_contents_data[i]->mru_features_.index = i;
      web_contents_data[i]->mru_features_.total = total_tabs;
    }

    // Add will_be_closed tabs to |all_closing_tabs_| set.
    int count = tab_strip_model->count();
    for (int i = 0; i < count; i++) {
      auto* other = WebContentsData::FromWebContents(
          tab_strip_model->GetWebContentsAt(i));
      all_closing_tabs_.insert(other);
    }
  }
}

// Clears all_closing_tabs_ if CloseAllTabs is canceled or completed.
void TabActivityWatcher::CloseAllTabsStopped(TabStripModel* tab_strip_model,
                                             CloseAllStoppedReason reason) {
  all_closing_tabs_.clear();
}

void TabActivityWatcher::OnTabClosed(WebContentsData* web_contents_data) {
  // Log TabLifetime event.
  tab_metrics_logger_->LogTabLifetime(
      web_contents_data->ukm_source_id_,
      NowTicks() - web_contents_data->navigation_time_);

  // Log ForegroundedOrClosed event.
  if (!web_contents_data->backgrounded_time_.is_null()) {
    web_contents_data->LogForegroundedOrClosedMetrics(
        false /*is_foregrounded */);
  }

  // Erase the pointer in |all_closing_tabs_| only when all logging finished.
  all_closing_tabs_.erase(web_contents_data);
}

}  // namespace resource_coordinator
