chromium/ios/chrome/browser/autofill/ui_bundled/manual_fill/form_observer_helper.mm

// Copyright 2018 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/autofill/ui_bundled/manual_fill/form_observer_helper.h"

#import "components/autofill/ios/form_util/form_activity_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"

@interface FormObserverHelper ()<FormActivityObserver, WebStateListObserving>
// The WebStateList this instance is observing in order to update the
// active WebState.
@property(nonatomic, assign) WebStateList* webStateList;

// The WebState this instance is observing. Can be nullptr.
@property(nonatomic, assign) web::WebState* webState;

@end

@implementation FormObserverHelper {
  // Bridge to observe the web state list from Objective-C.
  std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;

  // Bridge to observe form activity in `_webState`.
  std::unique_ptr<autofill::FormActivityObserverBridge>
      _formActivityObserverBridge;
}

@synthesize delegate = _delegate;

- (instancetype)initWithWebStateList:(WebStateList*)webStateList {
  DCHECK(webStateList);
  self = [super init];
  if (self) {
    _webStateList = webStateList;
    _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
    _webStateList->AddObserver(_webStateListObserver.get());
    web::WebState* webState = webStateList->GetActiveWebState();
    if (webState) {
      _webState = webState;
      _formActivityObserverBridge =
          std::make_unique<autofill::FormActivityObserverBridge>(_webState,
                                                                 self);
    }
  }
  return self;
}

- (void)dealloc {
  [self disconnect];
}

#pragma mark - FormActivityObserver

- (void)webState:(web::WebState*)webState
    didRegisterFormActivity:(const autofill::FormActivityParams&)params
                    inFrame:(web::WebFrame*)frame {
  if ([self.delegate respondsToSelector:@selector
                     (webState:didRegisterFormActivity:inFrame:)]) {
    [self.delegate webState:webState
        didRegisterFormActivity:params
                        inFrame:frame];
  }
}

- (void)webState:(web::WebState*)webState
    didSubmitDocumentWithFormNamed:(const std::string&)formName
                          withData:(const std::string&)formData
                    hasUserGesture:(BOOL)hasUserGesture
                           inFrame:(web::WebFrame*)frame {
  if ([self.delegate respondsToSelector:@selector
                     (webState:
                         didSubmitDocumentWithFormNamed:withData:hasUserGesture
                                                       :inFrame:)]) {
    [self.delegate webState:webState
        didSubmitDocumentWithFormNamed:formName
                              withData:formData
                        hasUserGesture:hasUserGesture
                               inFrame:frame];
  }
}

#pragma mark - WebStateListObserving

- (void)didChangeWebStateList:(WebStateList*)webStateList
                       change:(const WebStateListChange&)change
                       status:(const WebStateListStatus&)status {
  if (status.active_web_state_change()) {
    self.webState = status.new_active_web_state;
  }
}

- (void)webStateListDestroyed:(WebStateList*)webStateList {
  [self disconnect];
}

#pragma mark - Setters

// Sets the new web state and detaches from the previous web state.
- (void)setWebState:(web::WebState*)webState {
  if (_webState) {
    _formActivityObserverBridge.reset();
  }

  _webState = webState;

  if (_webState) {
    _formActivityObserverBridge =
        std::make_unique<autofill::FormActivityObserverBridge>(_webState, self);
  }
}

#pragma mark - Private

- (void)disconnect {
  if (_webState) {
    _formActivityObserverBridge.reset();
    _webState = nullptr;
  }
  if (_webStateList) {
    _webStateList->RemoveObserver(_webStateListObserver.get());
    _webStateListObserver.reset();
    _webStateList = nullptr;
  }
}

@end