chromium/ios/chrome/browser/ui/toolbar/secondary_toolbar_mediator.mm

// Copyright 2023 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/ui/toolbar/secondary_toolbar_mediator.h"

#import "base/memory/weak_ptr.h"
#import "ios/chrome/browser/contextual_panel/model/active_contextual_panel_tab_helper_observation_forwarder.h"
#import "ios/chrome/browser/contextual_panel/model/contextual_panel_tab_helper.h"
#import "ios/chrome/browser/contextual_panel/model/contextual_panel_tab_helper_observer_bridge.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer_bridge.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/ui/toolbar/secondary_toolbar_consumer.h"
#import "ios/web/public/ui/crw_web_view_proxy.h"
#import "ios/web/public/web_state.h"

@interface SecondaryToolbarMediator () <ContextualPanelTabHelperObserving,
                                        WebStateListObserving>

@end

@implementation SecondaryToolbarMediator {
  // The Browser's WebStateList.
  base::WeakPtr<WebStateList> _webStateList;

  // Observer machinery for the web state list.
  std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
  std::unique_ptr<
      base::ScopedObservation<WebStateList, WebStateListObserverBridge>>
      _webStateListObservation;

  // Bridge for the ContextualPanelTabHelper observation.
  std::unique_ptr<ContextualPanelTabHelperObserverBridge>
      _contextualPanelObserverBridge;

  // Forwarder to always be observing the active ContextualPanelTabHelper.
  std::unique_ptr<ActiveContextualPanelTabHelperObservationForwarder>
      _activeContextualPanelObservationForwarder;
}

- (instancetype)initWithWebStateList:(WebStateList*)webStateList {
  if ((self = [super init])) {
    DCHECK(webStateList);
    _webStateList = webStateList->AsWeakPtr();

    // Web state list observation is only necessary for Contextual Panel
    // feature.
    if (IsContextualPanelEnabled()) {
      // Set up web state list observation.
      _webStateListObserver =
          std::make_unique<WebStateListObserverBridge>(self);
      _webStateListObservation = std::make_unique<
          base::ScopedObservation<WebStateList, WebStateListObserverBridge>>(
          _webStateListObserver.get());
      _webStateListObservation->Observe(_webStateList.get());

      // Set up active ContextualPanelTabHelper observation.
      _contextualPanelObserverBridge =
          std::make_unique<ContextualPanelTabHelperObserverBridge>(self);
      _activeContextualPanelObservationForwarder =
          std::make_unique<ActiveContextualPanelTabHelperObservationForwarder>(
              webStateList, _contextualPanelObserverBridge.get());
    }
  }
  return self;
}

- (void)disconnect {
  if (_webStateList) {
    _activeContextualPanelObservationForwarder.reset();
    _webStateListObservation.reset();
    _webStateList.reset();
  }
  _contextualPanelObserverBridge.reset();
  _webStateListObserver.reset();
}

#pragma mark - SecondaryToolbarKeyboardStateProvider

- (BOOL)keyboardIsActiveForWebContent {
  if (_webStateList && _webStateList->GetActiveWebState()) {
    return _webStateList->GetActiveWebState()
        ->GetWebViewProxy()
        .keyboardVisible;
  }
  return NO;
}

#pragma mark - WebStateListObserving

- (void)didChangeWebStateList:(WebStateList*)webStateList
                       change:(const WebStateListChange&)change
                       status:(const WebStateListStatus&)status {
  // Return early if the active web state is the same as before the change.
  if (!status.active_web_state_change()) {
    return;
  }

  // Return early if no new webstates are active.
  if (!status.new_active_web_state) {
    return;
  }
  ContextualPanelTabHelper* contextualPanelTabHelper =
      ContextualPanelTabHelper::FromWebState(status.new_active_web_state);
  if (!contextualPanelTabHelper) {
    return;
  }

  if (contextualPanelTabHelper->IsContextualPanelCurrentlyOpened()) {
    [self.consumer makeTranslucent];
  } else {
    [self.consumer makeOpaque];
  }
}

#pragma mark - ContextualPanelTabHelperObserving

- (void)contextualPanelOpened:(ContextualPanelTabHelper*)tabHelper {
  [self.consumer makeTranslucent];
}

- (void)contextualPanelClosed:(ContextualPanelTabHelper*)tabHelper {
  [self.consumer makeOpaque];
}

@end