// 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_lifecycle_unit.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/process/process_metrics.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/resource_coordinator/intervention_policy_database.h"
#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h"
#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h"
#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
#include "chrome/browser/resource_coordinator/tab_helper.h"
#include "chrome/browser/resource_coordinator/tab_lifecycle_observer.h"
#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h"
#include "chrome/browser/resource_coordinator/tab_load_tracker.h"
#include "chrome/browser/resource_coordinator/tab_manager_features.h"
#include "chrome/browser/resource_coordinator/time.h"
#include "chrome/browser/resource_coordinator/utils.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/usb/usb_tab_helper.h"
#include "components/device_event_log/device_event_log.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"

namespace resource_coordinator {

namespace {

using StateChangeReason = LifecycleUnitStateChangeReason;

bool IsDiscardedOrPendingDiscard(LifecycleUnitState state) {
  return state == LifecycleUnitState::DISCARDED ||
         state == LifecycleUnitState::PENDING_DISCARD;
}

bool IsFrozenOrPendingFreeze(LifecycleUnitState state) {
  return state == LifecycleUnitState::FROZEN ||
         state == LifecycleUnitState::PENDING_FREEZE;
}

// Returns true if it is valid to transition from |from| to |to| for |reason|.
bool IsValidStateChange(LifecycleUnitState from,
                        LifecycleUnitState to,
                        StateChangeReason reason) {
  switch (from) {
    case LifecycleUnitState::ACTIVE: {
      switch (to) {
        // Freeze() is called.
        case LifecycleUnitState::PENDING_FREEZE:
        // Discard(PROACTIVE) is called.
        case LifecycleUnitState::PENDING_DISCARD:
          return reason == StateChangeReason::BROWSER_INITIATED;
        // Discard(URGENT|EXTERNAL) is called.
        case LifecycleUnitState::DISCARDED: {
          return reason == StateChangeReason::SYSTEM_MEMORY_PRESSURE ||
                 reason == StateChangeReason::EXTENSION_INITIATED;
        }
        case LifecycleUnitState::FROZEN: {
          // Render-initiated freezing, which happens when freezing a page
          // through ChromeDriver.
          return reason == StateChangeReason::RENDERER_INITIATED;
        }
        default:
          return false;
      }
    }
    case LifecycleUnitState::THROTTLED: {
      return false;
    }
    case LifecycleUnitState::PENDING_FREEZE: {
      switch (to) {
        // Discard(PROACTIVE) is called.
        case LifecycleUnitState::PENDING_DISCARD:
          return reason == StateChangeReason::BROWSER_INITIATED;
        // Discard(URGENT|EXTERNAL) is called.
        case LifecycleUnitState::DISCARDED:
          return reason == StateChangeReason::SYSTEM_MEMORY_PRESSURE ||
                 reason == StateChangeReason::EXTENSION_INITIATED;
        // The renderer notifies the browser that the page has been frozen.
        case LifecycleUnitState::FROZEN:
          return reason == StateChangeReason::RENDERER_INITIATED;
        // Unfreeze() is called.
        case LifecycleUnitState::PENDING_UNFREEZE:
          return reason == StateChangeReason::BROWSER_INITIATED;
        default:
          return false;
      }
    }
    case LifecycleUnitState::FROZEN: {
      switch (to) {
        // The renderer notifies the browser that the page was unfrozen after
        // it became visible.
        case LifecycleUnitState::ACTIVE: {
          return reason == StateChangeReason::RENDERER_INITIATED;
        }
        // Discard(PROACTIVE|URGENT|EXTERNAL) is called.
        case LifecycleUnitState::DISCARDED: {
          return reason == StateChangeReason::BROWSER_INITIATED ||
                 reason == StateChangeReason::SYSTEM_MEMORY_PRESSURE ||
                 reason == StateChangeReason::EXTENSION_INITIATED;
        }
        // Unfreeze() is called.
        case LifecycleUnitState::PENDING_UNFREEZE: {
          return reason == StateChangeReason::BROWSER_INITIATED;
        }
        default:
          return false;
      }
    }
    case LifecycleUnitState::PENDING_DISCARD: {
      switch (to) {
        // - Discard(URGENT|EXTERNAL) is called, or,
        // - The proactive discard can be completed because:
        //   - The freeze timeout expires, or,
        //   - The renderer notifies the browser that the page has been frozen.
        case LifecycleUnitState::DISCARDED:
          return reason == StateChangeReason::BROWSER_INITIATED ||
                 reason == StateChangeReason::SYSTEM_MEMORY_PRESSURE ||
                 reason == StateChangeReason::EXTENSION_INITIATED;
        // The WebContents is focused.
        case LifecycleUnitState::PENDING_FREEZE:
          return reason == StateChangeReason::USER_INITIATED;
        default:
          return false;
      }
    }
    case LifecycleUnitState::DISCARDED: {
      switch (to) {
        // The WebContents is focused or reloaded.
        case LifecycleUnitState::ACTIVE:
          return reason == StateChangeReason::USER_INITIATED;
        default:
          return false;
      }
    }
    case LifecycleUnitState::PENDING_UNFREEZE: {
      switch (to) {
        // The renderer notifies the browser that the page was unfrozen after
        // Unfreeze() was called in the browser.
        case LifecycleUnitState::ACTIVE: {
          return reason == StateChangeReason::RENDERER_INITIATED;
        }
        // Discard(URGENT|EXTERNAL) is called.
        case LifecycleUnitState::DISCARDED: {
          return reason == StateChangeReason::SYSTEM_MEMORY_PRESSURE ||
                 reason == StateChangeReason::EXTENSION_INITIATED;
        }
        default: { return false; }
      }
    }
  }
}

StateChangeReason DiscardReasonToStateChangeReason(
    LifecycleUnitDiscardReason reason) {
  switch (reason) {
    case LifecycleUnitDiscardReason::EXTERNAL:
      return StateChangeReason::EXTENSION_INITIATED;
    case LifecycleUnitDiscardReason::PROACTIVE:
      return StateChangeReason::BROWSER_INITIATED;
    case LifecycleUnitDiscardReason::URGENT:
      return StateChangeReason::SYSTEM_MEMORY_PRESSURE;
  }
}

struct FeatureUsageEntry {
  SiteFeatureUsage usage;
  DecisionFailureReason failure_reason;
};

void CheckFeatureUsage(const SiteCharacteristicsDataReader* reader,
                       DecisionDetails* details) {
  const FeatureUsageEntry features[] = {
      {reader->UsesAudioInBackground(), DecisionFailureReason::HEURISTIC_AUDIO},
      {reader->UpdatesFaviconInBackground(),
       DecisionFailureReason::HEURISTIC_FAVICON},
      {reader->UsesNotificationsInBackground(),
       DecisionFailureReason::HEURISTIC_NOTIFICATIONS},
      {reader->UpdatesTitleInBackground(),
       DecisionFailureReason::HEURISTIC_TITLE}};

  // Avoid adding 'insufficient observation' reason multiple times.
  bool insufficient_observation = false;

  const auto* last = features + base::size(features);
  for (const auto* f = features; f != last; f++) {
    if (f->usage == SiteFeatureUsage::kSiteFeatureInUse) {
      details->AddReason(f->failure_reason);
    } else if (f->usage == SiteFeatureUsage::kSiteFeatureUsageUnknown) {
      insufficient_observation = true;
    }
  }

  if (insufficient_observation) {
    details->AddReason(
        DecisionFailureReason::HEURISTIC_INSUFFICIENT_OBSERVATION);
  }
}

void CheckIfTabCanCommunicateWithUserWhileInBackground(
    content::WebContents* web_contents,
    DecisionDetails* details) {
  DCHECK(details);

  if (!web_contents->GetLastCommittedURL().is_valid() ||
      web_contents->GetLastCommittedURL().is_empty()) {
    return;
  }

  if (!URLShouldBeStoredInLocalDatabase(web_contents->GetLastCommittedURL()))
    return;

  SiteCharacteristicsDataStore* data_store =
      LocalSiteCharacteristicsDataStoreFactory::GetForProfile(
          Profile::FromBrowserContext(web_contents->GetBrowserContext()));
  if (!data_store)
    return;

  auto reader = data_store->GetReaderForOrigin(
      url::Origin::Create(web_contents->GetLastCommittedURL()));

  // TODO(sebmarchand): Add a failure reason for when the data isn't ready yet.

  CheckFeatureUsage(reader.get(), details);
}

}  // namespace

class TabLifecycleUnitExternalImpl : public TabLifecycleUnitExternal {
 public:
  explicit TabLifecycleUnitExternalImpl(
      TabLifecycleUnitSource::TabLifecycleUnit* tab_lifecycle_unit)
      : tab_lifecycle_unit_(tab_lifecycle_unit) {}

  // TabLifecycleUnitExternal:

  content::WebContents* GetWebContents() const override {
    return tab_lifecycle_unit_->web_contents();
  }

  bool IsMediaTab() const override { return tab_lifecycle_unit_->IsMediaTab(); }

  bool IsAutoDiscardable() const override {
    return tab_lifecycle_unit_->IsAutoDiscardable();
  }

  void SetAutoDiscardable(bool auto_discardable) override {
    tab_lifecycle_unit_->SetAutoDiscardable(auto_discardable);
  }

  bool DiscardTab() override {
    return tab_lifecycle_unit_->Discard(LifecycleUnitDiscardReason::EXTERNAL);
  }

  bool IsDiscarded() const override {
    // External code does not need to know about the intermediary
    // PENDING_DISCARD state. To external callers, the tab is discarded while in
    // the PENDING_DISCARD state.
    return IsDiscardedOrPendingDiscard(tab_lifecycle_unit_->GetState());
  }

  int GetDiscardCount() const override {
    return tab_lifecycle_unit_->GetDiscardCount();
  }

 private:
  TabLifecycleUnitSource::TabLifecycleUnit* tab_lifecycle_unit_ = nullptr;
};

TabLifecycleUnitSource::TabLifecycleUnit::TabLifecycleUnit(
    TabLifecycleUnitSource* source,
    base::ObserverList<TabLifecycleObserver>::Unchecked* observers,
    UsageClock* usage_clock,
    content::WebContents* web_contents,
    TabStripModel* tab_strip_model)
    : LifecycleUnitBase(source, web_contents->GetVisibility(), usage_clock),
      content::WebContentsObserver(web_contents),
      observers_(observers),
      tab_strip_model_(tab_strip_model) {
  DCHECK(observers_);
  DCHECK(web_contents);
  DCHECK(tab_strip_model_);

  // Attach the ResourceCoordinatorTabHelper. In production code this has
  // already been attached by now due to AttachTabHelpers, but there's a long
  // tail of tests that don't add these helpers. This ensures that the various
  // DCHECKs in the state transition machinery don't fail.
  ResourceCoordinatorTabHelper::CreateForWebContents(web_contents);

  // Visible tabs are treated as having been immediately focused, while
  // non-visible tabs have their focus set to the last active time (the time at
  // which they stopped being the active tab in a tabstrip).
  if (GetVisibility() == content::Visibility::VISIBLE)
    last_focused_time_ = NowTicks();
  else
    last_focused_time_ = web_contents->GetLastActiveTime();
}

TabLifecycleUnitSource::TabLifecycleUnit::~TabLifecycleUnit() {
  OnLifecycleUnitDestroyed();
}

void TabLifecycleUnitSource::TabLifecycleUnit::SetTabStripModel(
    TabStripModel* tab_strip_model) {
  tab_strip_model_ = tab_strip_model;
}

void TabLifecycleUnitSource::TabLifecycleUnit::SetWebContents(
    content::WebContents* web_contents) {
  DCHECK(web_contents);
  Observe(web_contents);
}

void TabLifecycleUnitSource::TabLifecycleUnit::SetFocused(bool focused) {
  const bool was_focused = last_focused_time_ == base::TimeTicks::Max();
  if (focused == was_focused)
    return;
  last_focused_time_ = focused ? base::TimeTicks::Max() : NowTicks();

  if (!focused)
    return;

  switch (GetState()) {
    case LifecycleUnitState::DISCARDED: {
      // Reload the tab.
      SetState(LifecycleUnitState::ACTIVE, StateChangeReason::USER_INITIATED);
      bool loaded = Load();
      DCHECK(loaded);
      break;
    }

    case LifecycleUnitState::PENDING_DISCARD: {
      // PENDING_DISCARD indicates that a freeze request is being processed by
      // the renderer and that the page should be discarded as soon as it is
      // frozen. On focus, we transition the state to PENDING_FREEZE and we stop
      // the freeze timeout timer to indicate that a freeze request is being
      // processed, but that the page should not be discarded once frozen. After
      // the renderer has processed the freeze request, it will realize that the
      // page is focused, unfreeze it and initiate a transition to ACTIVE.
      freeze_timeout_timer_->Stop();
      SetState(LifecycleUnitState::PENDING_FREEZE,
               StateChangeReason::USER_INITIATED);
      break;
    }

    default:
      break;
  }
}

void TabLifecycleUnitSource::TabLifecycleUnit::SetRecentlyAudible(
    bool recently_audible) {
  if (recently_audible)
    recently_audible_time_ = base::TimeTicks::Max();
  else if (recently_audible_time_ == base::TimeTicks::Max())
    recently_audible_time_ = NowTicks();
}

void TabLifecycleUnitSource::TabLifecycleUnit::UpdateLifecycleState(
    mojom::LifecycleState state) {
  switch (state) {
    case mojom::LifecycleState::kFrozen: {
      switch (GetState()) {
        case LifecycleUnitState::PENDING_DISCARD: {
          freeze_timeout_timer_->Stop();
          FinishDiscard(GetDiscardReason());
          break;
        }
        case LifecycleUnitState::PENDING_UNFREEZE: {
          // By the time the kFrozen state message arrive the tab might have
          // been reloaded by the user (by right-clicking on the tab) and might
          // have been switched to the PENDING_UNFREEZE state. It's safe to just
          // ignore this message here as an unfreeze signal has been sent to the
          // tab and so a |kRunning| transition will follow this one.
          break;
        }
        default: {
          SetState(LifecycleUnitState::FROZEN,
                   StateChangeReason::RENDERER_INITIATED);
        }
      }
      break;
    }

    case mojom::LifecycleState::kRunning: {
      SetState(LifecycleUnitState::ACTIVE,
               StateChangeReason::RENDERER_INITIATED);
      break;
    }

    default: {
      NOTREACHED();
      break;
    }
  }
}

void TabLifecycleUnitSource::TabLifecycleUnit::RequestFreezeForDiscard(
    LifecycleUnitDiscardReason reason) {
  DCHECK_EQ(reason, LifecycleUnitDiscardReason::PROACTIVE);

  SetState(LifecycleUnitState::PENDING_DISCARD,
           DiscardReasonToStateChangeReason(reason));
  EnsureFreezeTimeoutTimerInitialized();
  freeze_timeout_timer_->Start(
      FROM_HERE, kProactiveDiscardFreezeTimeout,
      base::BindRepeating(&TabLifecycleUnit::FinishDiscard,
                          base::Unretained(this), reason));
  web_contents()->SetPageFrozen(true);
}

TabLifecycleUnitExternal*
TabLifecycleUnitSource::TabLifecycleUnit::AsTabLifecycleUnitExternal() {
  // Create an impl the first time this is called.
  if (!external_impl_)
    external_impl_ = std::make_unique<TabLifecycleUnitExternalImpl>(this);
  return external_impl_.get();
}

base::string16 TabLifecycleUnitSource::TabLifecycleUnit::GetTitle() const {
  return web_contents()->GetTitle();
}

base::TimeTicks TabLifecycleUnitSource::TabLifecycleUnit::GetLastFocusedTime()
    const {
  return last_focused_time_;
}

base::ProcessHandle TabLifecycleUnitSource::TabLifecycleUnit::GetProcessHandle()
    const {
  content::RenderFrameHost* main_frame = web_contents()->GetMainFrame();
  if (!main_frame)
    return base::ProcessHandle();
  content::RenderProcessHost* process = main_frame->GetProcess();
  if (!process)
    return base::ProcessHandle();
  return process->GetProcess().Handle();
}

LifecycleUnit::SortKey TabLifecycleUnitSource::TabLifecycleUnit::GetSortKey()
    const {
  if (base::FeatureList::IsEnabled(features::kTabRanker)) {
    const base::Optional<float> reactivation_score =
        resource_coordinator::TabActivityWatcher::GetInstance()
            ->CalculateReactivationScore(web_contents());
    if (reactivation_score.has_value())
      return SortKey(reactivation_score.value(), last_focused_time_);
    return SortKey(SortKey::kMaxScore, last_focused_time_);
  }

  return SortKey(last_focused_time_);
}

content::Visibility TabLifecycleUnitSource::TabLifecycleUnit::GetVisibility()
    const {
  return web_contents()->GetVisibility();
}

LifecycleUnitLoadingState
TabLifecycleUnitSource::TabLifecycleUnit::GetLoadingState() const {
  return TabLoadTracker::Get()->GetLoadingState(web_contents());
}

bool TabLifecycleUnitSource::TabLifecycleUnit::Load() {
  if (GetLoadingState() != LifecycleUnitLoadingState::UNLOADED)
    return false;

  // TODO(chrisha): Make this work more elegantly in the case of background tab
  // loading as well, which uses a NavigationThrottle that can be released.

  // See comment in Discard() for an explanation of why "needs reload" is
  // false when a tab is discarded.
  // TODO(fdoray): Remove NavigationControllerImpl::needs_reload_ once
  // session restore is handled by LifecycleManager.
  web_contents()->GetController().SetNeedsReload();
  web_contents()->GetController().LoadIfNecessary();
  return true;
}

int TabLifecycleUnitSource::TabLifecycleUnit::
    GetEstimatedMemoryFreedOnDiscardKB() const {
  return GetPrivateMemoryKB(GetProcessHandle());
}

bool TabLifecycleUnitSource::TabLifecycleUnit::CanPurge() const {
  // A renderer can be purged if it's not playing media.
  return !IsMediaTabImpl(nullptr);
}

bool TabLifecycleUnitSource::TabLifecycleUnit::CanFreeze(
    DecisionDetails* decision_details) const {
  DCHECK(decision_details->reasons().empty());

  // Leave the |decision_details| empty and return immediately for "trivial"
  // rejection reasons. These aren't worth reporting about, as they have nothing
  // to do with the content itself.

  if (!IsValidStateChange(GetState(), LifecycleUnitState::PENDING_FREEZE,
                          StateChangeReason::BROWSER_INITIATED)) {
    return false;
  }

  // Allow a page to load fully before freezing it.
  if (TabLoadTracker::Get()->GetLoadingState(web_contents()) !=
      TabLoadTracker::LoadingState::LOADED) {
    return false;
  }

  bool check_heuristics = !GetStaticProactiveTabFreezeAndDiscardParams()
                               .disable_heuristics_protections;

  if (check_heuristics)
    CanFreezeHeuristicsChecks(decision_details);

  if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
    decision_details->AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE);

  if (check_heuristics) {
    CheckIfTabIsUsedInBackground(decision_details,
                                 InterventionType::kProactive);
  }

  if (decision_details->reasons().empty()) {
    decision_details->AddReason(
        DecisionSuccessReason::HEURISTIC_OBSERVED_TO_BE_SAFE);
  }

  return decision_details->IsPositive();
}

bool TabLifecycleUnitSource::TabLifecycleUnit::CanDiscard(
    LifecycleUnitDiscardReason reason,
    DecisionDetails* decision_details) const {
  DCHECK(decision_details->reasons().empty());

  // Leave the |decision_details| empty and return immediately for "trivial"
  // rejection reasons. These aren't worth reporting about, as they have nothing
  // to do with the content itself.

  // Can't discard a tab that isn't in a TabStripModel.
  if (!tab_strip_model_)
    return false;

  const LifecycleUnitState target_state =
      reason == LifecycleUnitDiscardReason::PROACTIVE &&
              GetState() != LifecycleUnitState::FROZEN
          ? LifecycleUnitState::PENDING_DISCARD
          : LifecycleUnitState::DISCARDED;
  if (!IsValidStateChange(GetState(), target_state,
                          DiscardReasonToStateChangeReason(reason))) {
    return false;
  }

  if (web_contents()->IsCrashed())
    return false;

  // Do not discard tabs that don't have a valid URL (most probably they have
  // just been opened and discarding them would lose the URL).
  // TODO(fdoray): Look into a workaround to be able to kill the tab without
  // losing the pending navigation.
  if (!web_contents()->GetLastCommittedURL().is_valid() ||
      web_contents()->GetLastCommittedURL().is_empty()) {
    return false;
  }

// Fix for urgent discarding woes in crbug.com/883071. These protections only
// apply on non-ChromeOS desktop platforms (Linux, Mac, Win).
// NOTE: These do not currently provide DecisionDetails!
#if !defined(OS_CHROMEOS)
  if (reason == LifecycleUnitDiscardReason::URGENT) {
    // Limit urgent discarding to once only.
    if (GetDiscardCount() > 0)
      return false;
    // Protect non-visible tabs from urgent discarding for a period of time.
    if (web_contents()->GetVisibility() != content::Visibility::VISIBLE) {
      base::TimeDelta time_in_bg = NowTicks() - GetWallTimeWhenHidden();
      if (time_in_bg < kBackgroundUrgentProtectionTime)
        return false;
    }
  }
#endif

  bool check_heuristics = !GetStaticProactiveTabFreezeAndDiscardParams()
                               .disable_heuristics_protections;

  if (check_heuristics)
    CanDiscardHeuristicsChecks(decision_details, reason);

#if defined(OS_CHROMEOS)
  if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
    decision_details->AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE);
#else
  // Do not discard the tab if it is currently active in its window.
  if (tab_strip_model_->GetActiveWebContents() == web_contents())
    decision_details->AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE);
#endif  // defined(OS_CHROMEOS)

  // Do not discard tabs in which the user has entered text in a form.
  if (web_contents()->GetPageImportanceSignals().had_form_interaction)
    decision_details->AddReason(DecisionFailureReason::LIVE_STATE_FORM_ENTRY);

  // Do not discard PDFs as they might contain entry that is not saved and they
  // don't remember their scrolling positions. See crbug.com/547286 and
  // crbug.com/65244.
  // TODO(fdoray): Remove this workaround when the bugs are fixed.
  if (web_contents()->GetContentsMimeType() == "application/pdf")
    decision_details->AddReason(DecisionFailureReason::LIVE_STATE_IS_PDF);

  // Do not discard a tab that was explicitly disallowed to.
  if (!auto_discardable_) {
    decision_details->AddReason(
        DecisionFailureReason::LIVE_STATE_EXTENSION_DISALLOWED);
  }

  if (check_heuristics) {
    CheckIfTabIsUsedInBackground(decision_details,
                                 reason == LifecycleUnitDiscardReason::PROACTIVE
                                     ? InterventionType::kProactive
                                     : InterventionType::kExternalOrUrgent);
  }

  if (decision_details->reasons().empty()) {
    decision_details->AddReason(
        DecisionSuccessReason::HEURISTIC_OBSERVED_TO_BE_SAFE);
    DCHECK(decision_details->IsPositive());
  }
  return decision_details->IsPositive();
}

bool TabLifecycleUnitSource::TabLifecycleUnit::Freeze() {
  if (!IsValidStateChange(GetState(), LifecycleUnitState::PENDING_FREEZE,
                          StateChangeReason::BROWSER_INITIATED)) {
    return false;
  }

  // WebContents::SetPageFrozen() DCHECKs if the page is visible.
  if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
    return false;

  SetState(LifecycleUnitState::PENDING_FREEZE,
           StateChangeReason::BROWSER_INITIATED);
  web_contents()->SetPageFrozen(true);
  return true;
}

bool TabLifecycleUnitSource::TabLifecycleUnit::Unfreeze() {
  if (!IsValidStateChange(GetState(), LifecycleUnitState::PENDING_UNFREEZE,
                          StateChangeReason::BROWSER_INITIATED)) {
    return false;
  }

  // WebContents::SetPageFrozen() DCHECKs if the page is visible.
  if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
    return false;

  SetState(LifecycleUnitState::PENDING_UNFREEZE,
           StateChangeReason::BROWSER_INITIATED);
  web_contents()->SetPageFrozen(false);
  return true;
}

ukm::SourceId TabLifecycleUnitSource::TabLifecycleUnit::GetUkmSourceId() const {
  resource_coordinator::ResourceCoordinatorTabHelper* observer =
      resource_coordinator::ResourceCoordinatorTabHelper::FromWebContents(
          web_contents());
  if (!observer)
    return ukm::kInvalidSourceId;
  return observer->ukm_source_id();
}

bool TabLifecycleUnitSource::TabLifecycleUnit::IsMediaTab() const {
  return IsMediaTabImpl(nullptr);
}

bool TabLifecycleUnitSource::TabLifecycleUnit::IsAutoDiscardable() const {
  return auto_discardable_;
}

void TabLifecycleUnitSource::TabLifecycleUnit::SetAutoDiscardable(
    bool auto_discardable) {
  if (auto_discardable_ == auto_discardable)
    return;
  auto_discardable_ = auto_discardable;
  for (auto& observer : *observers_)
    observer.OnAutoDiscardableStateChange(web_contents(), auto_discardable_);
}

void TabLifecycleUnitSource::TabLifecycleUnit::FinishDiscard(
    LifecycleUnitDiscardReason discard_reason) {
  UMA_HISTOGRAM_BOOLEAN(
      "TabManager.Discarding.DiscardedTabHasBeforeUnloadHandler",
      web_contents()->NeedToFireBeforeUnload());

  content::WebContents* const old_contents = web_contents();
  content::WebContents::CreateParams create_params(tab_strip_model_->profile());
  // TODO(fdoray): Consider setting |initially_hidden| to true when the tab is
  // OCCLUDED. Will require checking that the tab reload correctly when it
  // becomes VISIBLE.
  create_params.initially_hidden =
      old_contents->GetVisibility() == content::Visibility::HIDDEN;
  create_params.desired_renderer_state =
      content::WebContents::CreateParams::kNoRendererProcess;
  create_params.last_active_time = old_contents->GetLastActiveTime();
  std::unique_ptr<content::WebContents> null_contents =
      content::WebContents::Create(create_params);
  content::WebContents* raw_null_contents = null_contents.get();

  // Attach the ResourceCoordinatorTabHelper. In production code this has
  // already been attached by now due to AttachTabHelpers, but there's a long
  // tail of tests that don't add these helpers. This ensures that the various
  // DCHECKs in the state transition machinery don't fail.
  ResourceCoordinatorTabHelper::CreateForWebContents(raw_null_contents);

  // Copy over the state from the navigation controller to preserve the
  // back/forward history and to continue to display the correct title/favicon.
  //
  // Set |needs_reload| to false so that the tab is not automatically reloaded
  // when activated. If it was true, there would be an immediate reload when the
  // active tab of a non-visible window is discarded. SetFocused() will take
  // care of reloading the tab when it becomes active in a focused window.
  null_contents->GetController().CopyStateFrom(&old_contents->GetController(),
                                               /* needs_reload */ false);

  // First try to fast-kill the process, if it's just running a single tab.
  bool fast_shutdown_success =
      GetRenderProcessHost()->FastShutdownIfPossible(1u, false);

#if defined(OS_CHROMEOS)
  if (!fast_shutdown_success &&
      discard_reason == LifecycleUnitDiscardReason::URGENT) {
    content::RenderFrameHost* main_frame = old_contents->GetMainFrame();
    // We avoid fast shutdown on tabs with beforeunload handlers on the main
    // frame, as that is often an indication of unsaved user state.
    DCHECK(main_frame);
    if (!main_frame->GetSuddenTerminationDisablerState(
            blink::kBeforeUnloadHandler)) {
      fast_shutdown_success = GetRenderProcessHost()->FastShutdownIfPossible(
          1u, /* skip_unload_handlers */ true);
    }
    UMA_HISTOGRAM_BOOLEAN(
        "TabManager.Discarding.DiscardedTabCouldUnsafeFastShutdown",
        fast_shutdown_success);
  }
#endif
  UMA_HISTOGRAM_BOOLEAN("TabManager.Discarding.DiscardedTabCouldFastShutdown",
                        fast_shutdown_success);

  // Replace the discarded tab with the null version.
  const int index = tab_strip_model_->GetIndexOfWebContents(old_contents);
  DCHECK_NE(index, TabStripModel::kNoTab);

  // This ensures that on reload after discard, the document has
  // "WasDiscarded" set to true.
  // The "WasDiscarded" state is also sent to tab_strip_model.
  null_contents->SetWasDiscarded(true);

  std::unique_ptr<content::WebContents> old_contents_deleter =
      tab_strip_model_->ReplaceWebContentsAt(index, std::move(null_contents));
  DCHECK_EQ(web_contents(), raw_null_contents);

  // Discard the old tab's renderer.
  // TODO(jamescook): This breaks script connections with other tabs. Find a
  // different approach that doesn't do that, perhaps based on
  // RenderFrameProxyHosts.
  old_contents_deleter.reset();

  SetState(LifecycleUnitState::DISCARDED,
           DiscardReasonToStateChangeReason(discard_reason));
  DCHECK_EQ(GetLoadingState(), LifecycleUnitLoadingState::UNLOADED);
}

bool TabLifecycleUnitSource::TabLifecycleUnit::Discard(
    LifecycleUnitDiscardReason reason) {
  // Can't discard a tab when it isn't in a tabstrip.
  if (!tab_strip_model_) {
    // Logs are used to diagnose user feedback reports.
    MEMORY_LOG(ERROR) << "Skipped discarding " << GetTitle()
                      << " because it isn't in a tab strip.";
    return false;
  }

  const LifecycleUnitState target_state =
      reason == LifecycleUnitDiscardReason::PROACTIVE &&
              GetState() != LifecycleUnitState::FROZEN
          ? LifecycleUnitState::PENDING_DISCARD
          : LifecycleUnitState::DISCARDED;
  if (!IsValidStateChange(GetState(), target_state,
                          DiscardReasonToStateChangeReason(reason))) {
    // Logs are used to diagnose user feedback reports.
    MEMORY_LOG(ERROR) << "Skipped discarding " << GetTitle()
                      << " because a transition from " << GetState() << " to "
                      << target_state << " is not allowed.";
    return false;
  }

  discard_reason_ = reason;

  // If the tab is not going through an urgent discard, it should be frozen
  // first. Freeze the tab and set a timer to callback to FinishDiscard() in
  // case the freeze callback takes too long.
  //
  // TODO(fdoray): Request a freeze for EXTERNAL discards too once that doesn't
  // cause asynchronous change of tab id. https://crbug.com/632839
  if (target_state == LifecycleUnitState::PENDING_DISCARD)
    RequestFreezeForDiscard(reason);
  else
    FinishDiscard(reason);

  return true;
}

TabLifecycleUnitSource* TabLifecycleUnitSource::TabLifecycleUnit::GetTabSource()
    const {
  return static_cast<TabLifecycleUnitSource*>(GetSource());
}

bool TabLifecycleUnitSource::TabLifecycleUnit::IsMediaTabImpl(
    DecisionDetails* decision_details) const {
  // TODO(fdoray): Consider being notified of audible, capturing and mirrored
  // state changes via WebContentsDelegate::NavigationStateChanged() and/or
  // WebContentsObserver::OnAudioStateChanged and/or RecentlyAudibleHelper.
  // https://crbug.com/775644

  bool is_media_tab = false;

  if (recently_audible_time_ == base::TimeTicks::Max() ||
      (!recently_audible_time_.is_null() &&
       NowTicks() - recently_audible_time_ < kTabAudioProtectionTime)) {
    is_media_tab = true;
    if (decision_details) {
      decision_details->AddReason(
          DecisionFailureReason::LIVE_STATE_PLAYING_AUDIO);
    }
  }

  scoped_refptr<MediaStreamCaptureIndicator> media_indicator =
      MediaCaptureDevicesDispatcher::GetInstance()
          ->GetMediaStreamCaptureIndicator();

  if (media_indicator->IsCapturingUserMedia(web_contents())) {
    is_media_tab = true;
    if (decision_details)
      decision_details->AddReason(DecisionFailureReason::LIVE_STATE_CAPTURING);
  }

  if (media_indicator->IsBeingMirrored(web_contents())) {
    is_media_tab = true;
    if (decision_details)
      decision_details->AddReason(DecisionFailureReason::LIVE_STATE_MIRRORING);
  }

  if (media_indicator->IsCapturingDesktop(web_contents())) {
    is_media_tab = true;
    if (decision_details) {
      decision_details->AddReason(
          DecisionFailureReason::LIVE_STATE_DESKTOP_CAPTURE);
    }
  }

  return is_media_tab;
}

content::RenderProcessHost*
TabLifecycleUnitSource::TabLifecycleUnit::GetRenderProcessHost() const {
  return web_contents()->GetMainFrame()->GetProcess();
}

void TabLifecycleUnitSource::TabLifecycleUnit::
    EnsureFreezeTimeoutTimerInitialized() {
  if (!freeze_timeout_timer_) {
    freeze_timeout_timer_ =
        std::make_unique<base::OneShotTimer>(GetTickClock());
  }
}

void TabLifecycleUnitSource::TabLifecycleUnit::OnLifecycleUnitStateChanged(
    LifecycleUnitState last_state,
    LifecycleUnitStateChangeReason reason) {
  DCHECK(IsValidStateChange(last_state, GetState(), reason))
      << "Cannot transition TabLifecycleUnit state from " << last_state
      << " to " << GetState() << " with reason " << reason;

  // Invoke OnDiscardedStateChange() if necessary.
  const bool was_discarded = IsDiscardedOrPendingDiscard(last_state);
  const bool is_discarded = IsDiscardedOrPendingDiscard(GetState());
  if (was_discarded != is_discarded) {
    for (auto& observer : *observers_)
      observer.OnDiscardedStateChange(web_contents(), GetDiscardReason(),
                                      is_discarded);
  }
}

void TabLifecycleUnitSource::TabLifecycleUnit::DidStartLoading() {
  if (IsDiscardedOrPendingDiscard(GetState())) {
    // This happens when a discarded tab is explicitly reloaded without being
    // focused first (right-click > Reload).
    SetState(LifecycleUnitState::ACTIVE, StateChangeReason::USER_INITIATED);
  } else if (IsFrozenOrPendingFreeze(GetState())) {
    // This happens when a frozen tab is explicitly reloaded without being
    // focused first (right-click > Reload).
    Unfreeze();

    if (freeze_timeout_timer_)
      freeze_timeout_timer_->Stop();
  }
}

void TabLifecycleUnitSource::TabLifecycleUnit::OnVisibilityChanged(
    content::Visibility visibility) {
  OnLifecycleUnitVisibilityChanged(visibility);
}

void TabLifecycleUnitSource::TabLifecycleUnit::CheckIfTabIsUsedInBackground(
    DecisionDetails* decision_details,
    InterventionType intervention_type) const {
  DCHECK(decision_details);

  // We deliberately run through all of the logic without early termination.
  // This ensures that the decision details lists all possible reasons that the
  // transition can be denied.

  // Do not freeze tabs that are casting/mirroring/playing audio.
  IsMediaTabImpl(decision_details);

  if (GetStaticProactiveTabFreezeAndDiscardParams()
          .should_protect_tabs_sharing_browsing_instance) {
    if (web_contents()->GetSiteInstance()->GetRelatedActiveContentsCount() >
        1U) {
      decision_details->AddReason(
          DecisionFailureReason::LIVE_STATE_SHARING_BROWSING_INSTANCE);
    }
  }

  // Consult the local database to see if this tab could try to communicate with
  // the user while in background (don't check for the visibility here as
  // there's already a check for that above). Only do this for proactive
  // interventions.
  if (intervention_type == InterventionType::kProactive) {
    CheckIfTabCanCommunicateWithUserWhileInBackground(web_contents(),
                                                      decision_details);
  }

  // Do not freeze/discard a tab that has active WebUSB connections.
  if (auto* usb_tab_helper = UsbTabHelper::FromWebContents(web_contents())) {
    if (usb_tab_helper->IsDeviceConnected()) {
      decision_details->AddReason(
          DecisionFailureReason::LIVE_STATE_USING_WEB_USB);
    }
  }

  // Do not freeze tabs that are currently using DevTools.
  if (DevToolsWindow::GetInstanceForInspectedWebContents(web_contents())) {
    decision_details->AddReason(
        DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN);
  }
}

void TabLifecycleUnitSource::TabLifecycleUnit::CanFreezeHeuristicsChecks(
    DecisionDetails* decision_details) const {
  if (!GetTabSource()->tab_lifecycles_enterprise_policy()) {
    decision_details->AddReason(
        DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT);
  }

  auto intervention_policy =
      GetTabSource()->intervention_policy_database()->GetFreezingPolicy(
          url::Origin::Create(web_contents()->GetLastCommittedURL()));

  switch (intervention_policy) {
    case OriginInterventions::OPT_IN:
      decision_details->AddReason(DecisionSuccessReason::GLOBAL_WHITELIST);
      break;
    case OriginInterventions::OPT_OUT:
      decision_details->AddReason(DecisionFailureReason::GLOBAL_BLACKLIST);
      break;
    case OriginInterventions::DEFAULT:
      break;
  }
}

void TabLifecycleUnitSource::TabLifecycleUnit::CanDiscardHeuristicsChecks(
    DecisionDetails* decision_details,
    LifecycleUnitDiscardReason reason) const {
  // We deliberately run through all of the logic without early termination.
  // This ensures that the decision details lists all possible reasons that
  // the transition can be denied.
  if (!GetTabSource()->tab_lifecycles_enterprise_policy()) {
    decision_details->AddReason(
        DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT);
  }

  if (reason == LifecycleUnitDiscardReason::PROACTIVE) {
    auto intervention_policy =
        GetTabSource()->intervention_policy_database()->GetDiscardingPolicy(
            url::Origin::Create(web_contents()->GetLastCommittedURL()));

    switch (intervention_policy) {
      case OriginInterventions::OPT_IN:
        decision_details->AddReason(DecisionSuccessReason::GLOBAL_WHITELIST);
        break;
      case OriginInterventions::OPT_OUT:
        decision_details->AddReason(DecisionFailureReason::GLOBAL_BLACKLIST);
        break;
      case OriginInterventions::DEFAULT:
        break;
    }
  }
}

LifecycleUnitDiscardReason
TabLifecycleUnitSource::TabLifecycleUnit::GetDiscardReason() const {
  return discard_reason_;
}

}  // namespace resource_coordinator
