// Copyright 2018 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 "components/sync_sessions/local_session_event_handler_impl.h"

#include <algorithm>
#include <map>
#include <utility>
#include <vector>

#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync_sessions/sync_sessions_client.h"
#include "components/sync_sessions/synced_session_tracker.h"
#include "components/sync_sessions/synced_tab_delegate.h"
#include "components/sync_sessions/synced_window_delegate.h"
#include "components/sync_sessions/synced_window_delegates_getter.h"

namespace sync_sessions {
namespace {

using sessions::SerializedNavigationEntry;

// The maximum number of navigations in each direction we care to sync.
const int kMaxSyncNavigationCount = 6;

bool IsSessionRestoreInProgress(SyncSessionsClient* sessions_client) {
  DCHECK(sessions_client);
  SyncedWindowDelegatesGetter* synced_window_getter =
      sessions_client->GetSyncedWindowDelegatesGetter();
  SyncedWindowDelegatesGetter::SyncedWindowDelegateMap windows =
      synced_window_getter->GetSyncedWindowDelegates();
  for (const auto& window_iter_pair : windows) {
    if (window_iter_pair.second->IsSessionRestoreInProgress()) {
      return true;
    }
  }
  return false;
}

bool IsWindowSyncable(const SyncedWindowDelegate& window_delegate) {
  return window_delegate.ShouldSync() && window_delegate.GetTabCount() &&
         window_delegate.HasWindow();
}

// On Android, it's possible to not have any tabbed windows when only custom
// tabs are currently open. This means that there is tab data that will be
// restored later, but we cannot access it.
bool ScanForTabbedWindow(SyncedWindowDelegatesGetter* delegates_getter) {
  for (const auto& window_iter_pair :
       delegates_getter->GetSyncedWindowDelegates()) {
    const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
    if (window_delegate->IsTypeTabbed() && IsWindowSyncable(*window_delegate)) {
      return true;
    }
  }
  return false;
}

}  // namespace

LocalSessionEventHandlerImpl::WriteBatch::WriteBatch() = default;

LocalSessionEventHandlerImpl::WriteBatch::~WriteBatch() = default;

LocalSessionEventHandlerImpl::Delegate::~Delegate() = default;

LocalSessionEventHandlerImpl::LocalSessionEventHandlerImpl(
    Delegate* delegate,
    SyncSessionsClient* sessions_client,
    SyncedSessionTracker* session_tracker)
    : delegate_(delegate),
      sessions_client_(sessions_client),
      session_tracker_(session_tracker) {
  DCHECK(delegate);
  DCHECK(sessions_client);
  DCHECK(session_tracker);

  current_session_tag_ = session_tracker_->GetLocalSessionTag();
  DCHECK(!current_session_tag_.empty());

  if (!IsSessionRestoreInProgress(sessions_client)) {
    OnSessionRestoreComplete();
  }
}

LocalSessionEventHandlerImpl::~LocalSessionEventHandlerImpl() {}

void LocalSessionEventHandlerImpl::OnSessionRestoreComplete() {
  std::unique_ptr<WriteBatch> batch = delegate_->CreateLocalSessionWriteBatch();
  AssociateWindows(RELOAD_TABS, batch.get());
  batch->Commit();
}

sync_pb::SessionTab
LocalSessionEventHandlerImpl::GetTabSpecificsFromDelegateForTest(
    const SyncedTabDelegate& tab_delegate) const {
  return GetTabSpecificsFromDelegate(tab_delegate);
}

void LocalSessionEventHandlerImpl::AssociateWindows(ReloadTabsOption option,
                                                    WriteBatch* batch) {
  DCHECK(!IsSessionRestoreInProgress(sessions_client_));

  const bool has_tabbed_window =
      ScanForTabbedWindow(sessions_client_->GetSyncedWindowDelegatesGetter());

  // Note that |current_session| is a pointer owned by |session_tracker_|.
  // |session_tracker_| will continue to update |current_session| under
  // the hood so care must be taken accessing it. In particular, invoking
  // ResetSessionTracking(..) will invalidate all the tab data within
  // the session, hence why copies of the SyncedSession must be made ahead of
  // time.
  SyncedSession* current_session =
      session_tracker_->GetSession(current_session_tag_);

  SyncedWindowDelegatesGetter::SyncedWindowDelegateMap windows =
      sessions_client_->GetSyncedWindowDelegatesGetter()
          ->GetSyncedWindowDelegates();

  // Without native data, we need be careful not to obliterate any old
  // information, while at the same time handling updated tab ids. See
  // https://crbug.com/639009 for more info.
  if (has_tabbed_window) {
    // Just reset the session tracking. No need to worry about the previous
    // session; the current tabbed windows are now the source of truth.
    session_tracker_->ResetSessionTracking(current_session_tag_);
    current_session->modified_time = base::Time::Now();
  } else {
    DVLOG(1) << "Found no tabbed windows. Reloading "
             << current_session->windows.size()
             << " windows from previous session.";
  }

  for (auto& window_iter_pair : windows) {
    const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
    if (option == RELOAD_TABS) {
      UMA_HISTOGRAM_COUNTS_1M("Sync.SessionTabs",
                              window_delegate->GetTabCount());
    }

    // Make sure the window has tabs and a viewable window. The viewable
    // window check is necessary because, for example, when a browser is
    // closed the destructor is not necessarily run immediately. This means
    // its possible for us to get a handle to a browser that is about to be
    // removed. If the tab count is 0 or the window is null, the browser is
    // about to be deleted, so we ignore it.
    if (!IsWindowSyncable(*window_delegate)) {
      continue;
    }

    SessionID window_id = window_delegate->GetSessionId();
    DVLOG(1) << "Associating window " << window_id.id() << " with "
             << window_delegate->GetTabCount() << " tabs.";

    bool found_tabs = false;
    for (int j = 0; j < window_delegate->GetTabCount(); ++j) {
      SessionID tab_id = window_delegate->GetTabIdAt(j);
      SyncedTabDelegate* synced_tab = window_delegate->GetTabAt(j);

      // IsWindowSyncable(), via ShouldSync(), guarantees that tabs are not
      // null.
      DCHECK(synced_tab);

      // If for some reason the tab ID is invalid, skip it.
      if (!tab_id.is_valid()) {
        continue;
      }

      // Placeholder tabs are those without WebContents, either because they
      // were never loaded into memory or they were evicted from memory
      // (typically only on Android devices). They only have a window ID and a
      // tab ID,  and we can use the latter to properly reassociate the tab with
      // the entity that was backing it. The window ID could have changed, but
      // noone really cares, because the window/tab hierarchy is constructed
      // from the header entity (which has up-to-date IDs). Hence, in order to
      // avoid unnecessary traffic, we avoid updating the entity.
      if (!synced_tab->IsPlaceholderTab() && RELOAD_TABS == option) {
        AssociateTab(synced_tab, batch);
      }

      // If the tab was syncable, it would have been added to the tracker either
      // by the above AssociateTab call or by the OnLocalTabModified method
      // invoking AssociateTab directly. Therefore, we can key whether this
      // window has valid tabs based on the tab's presence in the tracker.
      const sessions::SessionTab* tab =
          session_tracker_->LookupSessionTab(current_session_tag_, tab_id);
      if (tab) {
        found_tabs = true;

        // Update this window's representation in the synced session tracker.
        // This is a no-op if called multiple times.
        session_tracker_->PutWindowInSession(current_session_tag_, window_id);

        // Put the tab in the window (must happen after the window is added
        // to the session).
        session_tracker_->PutTabInWindow(current_session_tag_, window_id,
                                         tab_id);
      }
    }
    if (found_tabs) {
      SyncedSessionWindow* synced_session_window =
          current_session->windows[window_id].get();
      if (window_delegate->IsTypeTabbed()) {
        synced_session_window->window_type =
            sync_pb::SessionWindow_BrowserType_TYPE_TABBED;
      } else if (window_delegate->IsTypePopup()) {
        synced_session_window->window_type =
            sync_pb::SessionWindow_BrowserType_TYPE_POPUP;
      } else {
        // This is a custom tab within an app. These will not be restored on
        // startup if not present.
        synced_session_window->window_type =
            sync_pb::SessionWindow_BrowserType_TYPE_CUSTOM_TAB;
      }
    }
  }

  std::set<int> deleted_tab_node_ids;
  session_tracker_->CleanupLocalTabs(&deleted_tab_node_ids);
  for (int tab_node_id : deleted_tab_node_ids) {
    batch->Delete(tab_node_id);
  }

  // Always update the header.  Sync takes care of dropping this update
  // if the entity specifics are identical (i.e windows, client name did
  // not change).
  auto specifics = std::make_unique<sync_pb::SessionSpecifics>();
  specifics->set_session_tag(current_session_tag_);
  current_session->ToSessionHeaderProto().Swap(specifics->mutable_header());
  batch->Put(std::move(specifics));
}

void LocalSessionEventHandlerImpl::AssociateTab(
    SyncedTabDelegate* const tab_delegate,
    WriteBatch* batch) {
  DCHECK(!tab_delegate->IsPlaceholderTab());

  if (tab_delegate->IsBeingDestroyed()) {
    task_tracker_.CleanTabTasks(tab_delegate->GetSessionId());
    // Do nothing else. By not proactively adding the tab to the session, it
    // will be removed if necessary during subsequent cleanup.
    return;
  }

  // Ensure the task tracker has up to date task ids for this tab.
  UpdateTaskTracker(tab_delegate);

  if (!tab_delegate->ShouldSync(sessions_client_)) {
    return;
  }

  SessionID tab_id = tab_delegate->GetSessionId();
  int tab_node_id =
      session_tracker_->LookupTabNodeFromTabId(current_session_tag_, tab_id);

  if (tab_node_id == TabNodePool::kInvalidTabNodeID) {
    // Allocate a new (or reused) sync node for this tab.
    tab_node_id = session_tracker_->AssociateLocalTabWithFreeTabNode(tab_id);
    DCHECK_NE(TabNodePool::kInvalidTabNodeID, tab_node_id)
        << "https://crbug.com/639009";
  }

  DVLOG(1) << "Syncing tab " << tab_id << " from window "
           << tab_delegate->GetWindowId() << " using tab node " << tab_node_id;

  // Get the previously synced url.
  sessions::SessionTab* session_tab =
      session_tracker_->GetTab(current_session_tag_, tab_id);
  int old_index = session_tab->normalized_navigation_index();
  GURL old_url;
  if (session_tab->navigations.size() > static_cast<size_t>(old_index))
    old_url = session_tab->navigations[old_index].virtual_url();

  // Produce the specifics.
  auto specifics = std::make_unique<sync_pb::SessionSpecifics>();
  specifics->set_session_tag(current_session_tag_);
  specifics->set_tab_node_id(tab_node_id);
  GetTabSpecificsFromDelegate(*tab_delegate).Swap(specifics->mutable_tab());
  WriteTasksIntoSpecifics(specifics->mutable_tab());

  // Update the tracker's session representation. Timestamp will be overwriten,
  // so we set a null time first to prevent the update from being ignored, if
  // the local clock is skewed.
  session_tab->timestamp = base::Time();
  UpdateTrackerWithSpecifics(*specifics, base::Time::Now(), session_tracker_);
  DCHECK(!session_tab->timestamp.is_null());

  // Write to the sync model itself.
  batch->Put(std::move(specifics));

  int current_index = tab_delegate->GetCurrentEntryIndex();
  const GURL new_url = tab_delegate->GetVirtualURLAtIndex(current_index);
  if (new_url != old_url) {
    delegate_->OnFaviconVisited(
        new_url, tab_delegate->GetFaviconURLAtIndex(current_index));
  }
}

void LocalSessionEventHandlerImpl::UpdateTaskTracker(
    SyncedTabDelegate* const tab_delegate) {
  TabTasks* tab_tasks = task_tracker_.GetTabTasks(
      tab_delegate->GetSessionId(), tab_delegate->GetSourceTabID());

  // Iterate through all navigations in the tab to ensure they all have a task
  // id set (it's possible some haven't been seen before, such as when a tab
  // is restored).
  for (int i = 0; i < tab_delegate->GetEntryCount(); ++i) {
    sessions::SerializedNavigationEntry serialized_entry;
    tab_delegate->GetSerializedNavigationAtIndex(i, &serialized_entry);

    int nav_id = serialized_entry.unique_id();
    int64_t global_id = serialized_entry.timestamp().ToInternalValue();
    tab_tasks->UpdateWithNavigation(
        nav_id, tab_delegate->GetTransitionAtIndex(i), global_id);
  }
}

void LocalSessionEventHandlerImpl::WriteTasksIntoSpecifics(
    sync_pb::SessionTab* tab_specifics) {
  TabTasks* tab_tasks = task_tracker_.GetTabTasks(
      SessionID::FromSerializedValue(tab_specifics->tab_id()),
      /*parent_tab_id=*/SessionID::InvalidValue());
  for (int i = 0; i < tab_specifics->navigation_size(); i++) {
    // Excluding blocked navigations, which are appended at tail.
    if (tab_specifics->navigation(i).blocked_state() ==
        sync_pb::TabNavigation::STATE_BLOCKED) {
      break;
    }

    std::vector<int64_t> task_ids = tab_tasks->GetTaskIdsForNavigation(
        tab_specifics->navigation(i).unique_id());
    if (task_ids.empty()) {
      continue;
    }

    tab_specifics->mutable_navigation(i)->set_task_id(task_ids.back());
    // Pop the task id of navigation self.
    task_ids.pop_back();
    tab_specifics->mutable_navigation(i)->clear_ancestor_task_id();
    for (auto ancestor_task_id : task_ids) {
      tab_specifics->mutable_navigation(i)->add_ancestor_task_id(
          ancestor_task_id);
    }
  }
}

void LocalSessionEventHandlerImpl::OnLocalTabModified(
    SyncedTabDelegate* modified_tab) {
  DCHECK(!current_session_tag_.empty());

  // Defers updates if session restore is in progress.
  if (IsSessionRestoreInProgress(sessions_client_)) {
    return;
  }

  sessions::SerializedNavigationEntry current;
  modified_tab->GetSerializedNavigationAtIndex(
      modified_tab->GetCurrentEntryIndex(), &current);
  delegate_->TrackLocalNavigationId(current.timestamp(), current.unique_id());

  std::unique_ptr<WriteBatch> batch = delegate_->CreateLocalSessionWriteBatch();
  AssociateTab(modified_tab, batch.get());
  // Note, we always associate windows because it's possible a tab became
  // "interesting" by going to a valid URL, in which case it needs to be added
  // to the window's tab information. Similarly, if a tab became
  // "uninteresting", we remove it from the window's tab information.
  AssociateWindows(DONT_RELOAD_TABS, batch.get());
  batch->Commit();
}

void LocalSessionEventHandlerImpl::OnFaviconsChanged(
    const std::set<GURL>& page_urls,
    const GURL& /* icon_url */) {
  for (const GURL& page_url : page_urls) {
    if (page_url.is_valid()) {
      delegate_->OnPageFaviconUpdated(page_url);
    }
  }
}

sync_pb::SessionTab LocalSessionEventHandlerImpl::GetTabSpecificsFromDelegate(
    const SyncedTabDelegate& tab_delegate) const {
  sync_pb::SessionTab specifics;
  specifics.set_window_id(tab_delegate.GetWindowId().id());
  specifics.set_tab_id(tab_delegate.GetSessionId().id());
  specifics.set_tab_visual_index(0);
  // Use -1 to indicate that the index hasn't been set properly yet.
  specifics.set_current_navigation_index(-1);
  const SyncedWindowDelegate* window_delegate =
      sessions_client_->GetSyncedWindowDelegatesGetter()->FindById(
          tab_delegate.GetWindowId());
  specifics.set_pinned(
      window_delegate ? window_delegate->IsTabPinned(&tab_delegate) : false);
  specifics.set_extension_app_id(tab_delegate.GetExtensionAppId());
  const int current_index = tab_delegate.GetCurrentEntryIndex();
  const int min_index = std::max(0, current_index - kMaxSyncNavigationCount);
  const int max_index = std::min(current_index + kMaxSyncNavigationCount,
                                 tab_delegate.GetEntryCount());
  bool is_supervised = tab_delegate.ProfileIsSupervised();

  for (int i = min_index; i < max_index; ++i) {
    if (!tab_delegate.GetVirtualURLAtIndex(i).is_valid()) {
      continue;
    }
    sessions::SerializedNavigationEntry serialized_entry;
    tab_delegate.GetSerializedNavigationAtIndex(i, &serialized_entry);

    // Set current_navigation_index to the index in navigations.
    if (i == current_index)
      specifics.set_current_navigation_index(specifics.navigation_size());

    sync_pb::TabNavigation* navigation = specifics.add_navigation();
    SessionNavigationToSyncData(serialized_entry).Swap(navigation);

    if (is_supervised) {
      navigation->set_blocked_state(
          sync_pb::TabNavigation_BlockedState_STATE_ALLOWED);
    }
  }

  // If the current navigation is invalid, set the index to the end of the
  // navigation array.
  if (specifics.current_navigation_index() < 0) {
    specifics.set_current_navigation_index(specifics.navigation_size() - 1);
  }

  if (is_supervised) {
    const std::vector<std::unique_ptr<const SerializedNavigationEntry>>&
        blocked_navigations = *tab_delegate.GetBlockedNavigations();
    for (size_t i = 0; i < blocked_navigations.size(); ++i) {
      sync_pb::TabNavigation* navigation = specifics.add_navigation();
      SessionNavigationToSyncData(*blocked_navigations[i]).Swap(navigation);
      navigation->set_blocked_state(
          sync_pb::TabNavigation_BlockedState_STATE_BLOCKED);
      // TODO(bauerb): Add categories
    }
  }

  return specifics;
}

}  // namespace sync_sessions
