chromium/ios/chrome/browser/web_state_list/model/web_state_dependency_installation_observer.mm

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/web_state_list/model/web_state_dependency_installation_observer.h"

#import "base/check.h"

WebStateDependencyInstallationObserver::WebStateDependencyInstallationObserver(
    WebStateList* web_state_list,
    DependencyInstaller* dependency_installer)
    : web_state_list_(web_state_list),
      dependency_installer_(dependency_installer) {
  DCHECK(web_state_list_);
  DCHECK(dependency_installer_);

  web_state_list_observation_.Observe(web_state_list_.get());
  for (int i = 0; i < web_state_list_->count(); i++) {
    OnWebStateAdded(web_state_list_->GetWebStateAt(i));
  }
}

WebStateDependencyInstallationObserver::
    ~WebStateDependencyInstallationObserver() {
  for (int i = 0; i < web_state_list_->count(); i++) {
    OnWebStateRemoved(web_state_list_->GetWebStateAt(i));
  }
}

#pragma mark - WebStateListObserver

void WebStateDependencyInstallationObserver::WebStateListDidChange(
    WebStateList* web_state_list,
    const WebStateListChange& change,
    const WebStateListStatus& status) {
  switch (change.type()) {
    case WebStateListChange::Type::kStatusOnly:
      // Do nothing when a WebState is selected and its status is updated.
      break;
    case WebStateListChange::Type::kDetach: {
      const WebStateListChangeDetach& detach_change =
          change.As<WebStateListChangeDetach>();
      OnWebStateRemoved(detach_change.detached_web_state());
      break;
    }
    case WebStateListChange::Type::kMove:
      // Do nothing when a WebState is moved.
      break;
    case WebStateListChange::Type::kReplace: {
      const WebStateListChangeReplace& replace_change =
          change.As<WebStateListChangeReplace>();
      OnWebStateRemoved(replace_change.replaced_web_state());
      OnWebStateAdded(replace_change.inserted_web_state());
      break;
    }
    case WebStateListChange::Type::kInsert: {
      const WebStateListChangeInsert& insert_change =
          change.As<WebStateListChangeInsert>();
      OnWebStateAdded(insert_change.inserted_web_state());
      break;
    }
    case WebStateListChange::Type::kGroupCreate:
      // Do nothing when a group is created.
      break;
    case WebStateListChange::Type::kGroupVisualDataUpdate:
      // Do nothing when a tab group's visual data are updated.
      break;
    case WebStateListChange::Type::kGroupMove:
      // Do nothing when a tab group is moved.
      break;
    case WebStateListChange::Type::kGroupDelete:
      // Do nothing when a group is deleted.
      break;
  }
}

void WebStateDependencyInstallationObserver::WebStateListDestroyed(
    WebStateList* web_state_list) {
  // Checking that all WebStates have been destroyed before destroying
  // the WebStateList, so we should not be observing anything.
  DCHECK(!web_state_observations_.IsObservingAnySource());
  web_state_list_observation_.Reset();
}

void WebStateDependencyInstallationObserver::OnWebStateAdded(
    web::WebState* web_state) {
  if (web_state->IsRealized()) {
    dependency_installer_->InstallDependency(web_state);
  } else if (!web_state_observations_.IsObservingSource(web_state)) {
    web_state_observations_.AddObservation(web_state);
  }
}

void WebStateDependencyInstallationObserver::OnWebStateRemoved(
    web::WebState* web_state) {
  if (web_state->IsRealized()) {
    dependency_installer_->UninstallDependency(web_state);
  } else if (web_state_observations_.IsObservingSource(web_state)) {
    web_state_observations_.RemoveObservation(web_state);
  }
}

void WebStateDependencyInstallationObserver::WebStateRealized(
    web::WebState* web_state) {
  web_state_observations_.RemoveObservation(web_state);
  OnWebStateAdded(web_state);
}

void WebStateDependencyInstallationObserver::WebStateDestroyed(
    web::WebState* web_state) {
  web_state_observations_.RemoveObservation(web_state);
}