// 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.

#include "chrome/browser/win/automation_controller.h"

#include <stdint.h>
#include <wrl/client.h>

#include <memory>
#include <utility>

#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/sequence_checker.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/thread_pool.h"
#include "base/win/atl.h"
#include "base/win/scoped_variant.h"
#include "chrome/browser/win/ui_automation_util.h"
#include "ui/base/win/atl_module.h"

namespace {

// Configures a cache request so that it includes all properties used by the
// debug logging.
void ConfigureCacheRequestForLogging(IUIAutomationCacheRequest* cache_request) {
  DCHECK(cache_request);
#if DCHECK_IS_ON()
  cache_request->AddProperty(UIA_AutomationIdPropertyId);
  cache_request->AddProperty(UIA_ClassNamePropertyId);
  cache_request->AddProperty(UIA_ControlTypePropertyId);
  cache_request->AddProperty(UIA_IsPeripheralPropertyId);
  cache_request->AddProperty(UIA_NamePropertyId);
  cache_request->AddProperty(UIA_ProcessIdPropertyId);
  cache_request->AddProperty(UIA_RuntimeIdPropertyId);
  cache_request->AddProperty(UIA_ValueValuePropertyId);
#endif  // DCHECK_IS_ON()
}

// Safely keeps |delegate_| alive and available for the Automation context and
// the event handlers. This is safe because only its vtable is accessed on the
// various threads, which is const.
class RefCountedDelegate : public base::RefCounted<RefCountedDelegate> {
 public:
  explicit RefCountedDelegate(
      std::unique_ptr<AutomationController::Delegate> delegate);

  RefCountedDelegate(const RefCountedDelegate&) = delete;
  RefCountedDelegate& operator=(const RefCountedDelegate&) = delete;

  // These are forwarded to |delegate_|.
  void OnInitialized(HRESULT result);
  void ConfigureCacheRequest(IUIAutomationCacheRequest* cache_request);
  void OnAutomationEvent(IUIAutomation* automation,
                         IUIAutomationElement* sender,
                         EVENTID event_id);
  void OnFocusChangedEvent(IUIAutomation* automation,
                           IUIAutomationElement* sender);

 private:
  friend class base::RefCounted<RefCountedDelegate>;
  ~RefCountedDelegate();

  const std::unique_ptr<AutomationController::Delegate> delegate_;
};

RefCountedDelegate::RefCountedDelegate(
    std::unique_ptr<AutomationController::Delegate> delegate)
    : delegate_(std::move(delegate)) {}

void RefCountedDelegate::OnInitialized(HRESULT result) {
  delegate_->OnInitialized(result);
}

void RefCountedDelegate::ConfigureCacheRequest(
    IUIAutomationCacheRequest* cache_request) {
  delegate_->ConfigureCacheRequest(cache_request);
}

void RefCountedDelegate::OnAutomationEvent(IUIAutomation* automation,
                                           IUIAutomationElement* sender,
                                           EVENTID event_id) {
  delegate_->OnAutomationEvent(automation, sender, event_id);
}

void RefCountedDelegate::OnFocusChangedEvent(IUIAutomation* automation,
                                             IUIAutomationElement* sender) {
  delegate_->OnFocusChangedEvent(automation, sender);
}

RefCountedDelegate::~RefCountedDelegate() = default;

}  // namespace

// This class lives in the automation sequence and is responsible for
// initializing the UIAutomation library and installing the event observers.
class AutomationController::Context {
 public:
  // Returns a new instance ready for initialization and use in another
  // sequence.
  static base::WeakPtr<Context> Create();

  Context(const Context&) = delete;
  Context& operator=(const Context&) = delete;

  // Deletes the instance.
  void DeleteInAutomationSequence();

  // Initializes the context, invoking the delegate's OnInitialized() method
  // when done. On success, the delegate's other On*() methods will be invoked
  // as events are observed. On failure, this instance self-destructs after
  // invoking OnInitialized().
  void Initialize(std::unique_ptr<Delegate> delegate);

 protected:
  class EventHandler;

  // The one and only method that may be called from outside of the automation
  // sequence.
  Context();
  ~Context();

  // Returns an event handler for all event types of interest.
  Microsoft::WRL::ComPtr<IUnknown> GetEventHandler();

  // Returns a pointer to the event handler's generic interface.
  Microsoft::WRL::ComPtr<IUIAutomationEventHandler> GetAutomationEventHandler();

  // Returns a pointer to the event handler's focus changed interface.
  Microsoft::WRL::ComPtr<IUIAutomationFocusChangedEventHandler>
  GetFocusChangedEventHandler();

  // Installs an event handler to observe events of interest.
  HRESULT InstallObservers();

  // Pointer to the delegate. Passed to event handlers.
  scoped_refptr<RefCountedDelegate> ref_counted_delegate_;

  SEQUENCE_CHECKER(sequence_checker_);

  // The automation client.
  Microsoft::WRL::ComPtr<IUIAutomation> automation_;

  // The event handler.
  Microsoft::WRL::ComPtr<IUnknown> event_handler_;

  // Weak pointers to the context are given to event handlers.
  base::WeakPtrFactory<Context> weak_ptr_factory_{this};
};

class AutomationController::Context::EventHandler
    : public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>,
      public IUIAutomationEventHandler,
      public IUIAutomationFocusChangedEventHandler {
 public:
  BEGIN_COM_MAP(AutomationController::Context::EventHandler)
  COM_INTERFACE_ENTRY(IUIAutomationEventHandler)
  COM_INTERFACE_ENTRY(IUIAutomationFocusChangedEventHandler)
  END_COM_MAP()

  EventHandler();

  EventHandler(const EventHandler&) = delete;
  EventHandler& operator=(const EventHandler&) = delete;

  ~EventHandler();

  // Initializes the object. Events will be dispatched back to |context| via
  // |context_runner|.
  void Initialize(Microsoft::WRL::ComPtr<IUIAutomation> automation,
                  scoped_refptr<RefCountedDelegate> ref_counted_delegate);

  // IUIAutomationEventHandler:
  STDMETHOD(HandleAutomationEvent)
  (IUIAutomationElement* sender, EVENTID event_id) override;

  // IUIAutomationFocusChangedEventHandler:
  STDMETHOD(HandleFocusChangedEvent)(IUIAutomationElement* sender) override;

 private:
  Microsoft::WRL::ComPtr<IUIAutomation> automation_;

  // Pointer to the delegate.
  scoped_refptr<RefCountedDelegate> ref_counted_delegate_;
};

AutomationController::Context::EventHandler::EventHandler() = default;

AutomationController::Context::EventHandler::~EventHandler() = default;

void AutomationController::Context::EventHandler::Initialize(
    Microsoft::WRL::ComPtr<IUIAutomation> automation,
    scoped_refptr<RefCountedDelegate> ref_counted_delegate) {
  automation_ = automation;
  ref_counted_delegate_ = std::move(ref_counted_delegate);
}

STDMETHODIMP
AutomationController::Context::EventHandler::HandleAutomationEvent(
    IUIAutomationElement* sender,
    EVENTID event_id) {
  DVLOG(1)
      << "event id: " << GetEventName(event_id) << ", automation id: "
      << GetCachedBstrValue(sender, UIA_AutomationIdPropertyId)
      << ", name: " << GetCachedBstrValue(sender, UIA_NamePropertyId)
      << ", control type: "
      << GetControlType(GetCachedInt32Value(sender, UIA_ControlTypePropertyId))
      << ", is peripheral: "
      << GetCachedBoolValue(sender, UIA_IsPeripheralPropertyId)
      << ", class name: " << GetCachedBstrValue(sender, UIA_ClassNamePropertyId)
      << ", pid: " << GetCachedInt32Value(sender, UIA_ProcessIdPropertyId)
      << ", value: " << GetCachedBstrValue(sender, UIA_ValueValuePropertyId)
      << ", runtime id: "
      << IntArrayToString(
             GetCachedInt32ArrayValue(sender, UIA_RuntimeIdPropertyId));

  ref_counted_delegate_->OnAutomationEvent(automation_.Get(), sender, event_id);

  return S_OK;
}

STDMETHODIMP
AutomationController::Context::EventHandler::HandleFocusChangedEvent(
    IUIAutomationElement* sender) {
  DVLOG(1)
      << "focus changed for automation id: "
      << GetCachedBstrValue(sender, UIA_AutomationIdPropertyId)
      << ", name: " << GetCachedBstrValue(sender, UIA_NamePropertyId)
      << ", control type: "
      << GetControlType(GetCachedInt32Value(sender, UIA_ControlTypePropertyId))
      << ", is peripheral: "
      << GetCachedBoolValue(sender, UIA_IsPeripheralPropertyId)
      << ", class name: " << GetCachedBstrValue(sender, UIA_ClassNamePropertyId)
      << ", pid: " << GetCachedInt32Value(sender, UIA_ProcessIdPropertyId)
      << ", value: " << GetCachedBstrValue(sender, UIA_ValueValuePropertyId)
      << ", runtime id: "
      << IntArrayToString(
             GetCachedInt32ArrayValue(sender, UIA_RuntimeIdPropertyId));

  ref_counted_delegate_->OnFocusChangedEvent(automation_.Get(), sender);

  return S_OK;
}

// AutomationController::Context
// --------------------------------------------------

// static
base::WeakPtr<AutomationController::Context>
AutomationController::Context::Create() {
  Context* context = new Context();
  return context->weak_ptr_factory_.GetWeakPtr();
}

void AutomationController::Context::DeleteInAutomationSequence() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delete this;
}

void AutomationController::Context::Initialize(
    std::unique_ptr<Delegate> delegate) {
  // This and all other methods must be called in the automation sequence.
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  ref_counted_delegate_ =
      base::MakeRefCounted<RefCountedDelegate>(std::move(delegate));

  HRESULT result =
      ::CoCreateInstance(CLSID_CUIAutomation, nullptr, CLSCTX_INPROC_SERVER,
                         IID_PPV_ARGS(&automation_));
  if (SUCCEEDED(result))
    result = automation_ ? InstallObservers() : E_FAIL;

  // Now that the observers are installed, it's time to signal that the
  // initialization is done and that events will be received.
  ref_counted_delegate_->OnInitialized(result);

  // Self-destruct immediately if initialization failed to reduce overhead.
  if (FAILED(result))
    delete this;
}

AutomationController::Context::Context() {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

AutomationController::Context::~Context() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (event_handler_) {
    event_handler_.Reset();
    automation_->RemoveAllEventHandlers();
  }
}

Microsoft::WRL::ComPtr<IUnknown>
AutomationController::Context::GetEventHandler() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!event_handler_) {
    ATL::CComObject<EventHandler>* obj = nullptr;
    HRESULT result = ATL::CComObject<EventHandler>::CreateInstance(&obj);
    if (SUCCEEDED(result)) {
      obj->Initialize(automation_, ref_counted_delegate_);
      obj->QueryInterface(IID_PPV_ARGS(&event_handler_));
    }
  }
  return event_handler_;
}

Microsoft::WRL::ComPtr<IUIAutomationEventHandler>
AutomationController::Context::GetAutomationEventHandler() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  Microsoft::WRL::ComPtr<IUIAutomationEventHandler> handler;
  GetEventHandler().As(&handler);
  return handler;
}

Microsoft::WRL::ComPtr<IUIAutomationFocusChangedEventHandler>
AutomationController::Context::GetFocusChangedEventHandler() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  Microsoft::WRL::ComPtr<IUIAutomationFocusChangedEventHandler> handler;
  GetEventHandler().As(&handler);
  return handler;
}

HRESULT AutomationController::Context::InstallObservers() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(automation_);

  // Create a cache request so that elements received by way of events contain
  // all data needed for processing.
  Microsoft::WRL::ComPtr<IUIAutomationCacheRequest> cache_request;
  HRESULT result = automation_->CreateCacheRequest(&cache_request);
  if (FAILED(result))
    return result;
  ConfigureCacheRequestForLogging(cache_request.Get());
  ref_counted_delegate_->ConfigureCacheRequest(cache_request.Get());

  // Observe changes in focus.
  result = automation_->AddFocusChangedEventHandler(
      cache_request.Get(), GetFocusChangedEventHandler().Get());
  if (FAILED(result))
    return result;

  // Observe invocations.
  Microsoft::WRL::ComPtr<IUIAutomationElement> desktop;
  result = automation_->GetRootElement(&desktop);
  if (desktop) {
    result = automation_->AddAutomationEventHandler(
        UIA_Invoke_InvokedEventId, desktop.Get(), TreeScope_Subtree,
        cache_request.Get(), GetAutomationEventHandler().Get());
  }

  return result;
}

// AutomationController --------------------------------------------------------

AutomationController::AutomationController(std::unique_ptr<Delegate> delegate) {
  ui::win::CreateATLModuleIfNeeded();

  // Create the task runner on which the automation client lives.
  automation_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
      {base::TaskPriority::USER_VISIBLE,
       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});

  // Initialize the context on the automation task runner.
  context_ = Context::Create();
  automation_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&AutomationController::Context::Initialize,
                                context_, std::move(delegate)));
}

AutomationController::~AutomationController() {
  // context_ is still valid when the caller destroys the instance before the
  // callback(s) have fired. In this case, delete the context in the automation
  // sequence before joining with it. DeleteSoon is not used because the monitor
  // has only a WeakPtr to the context that is bound to the automation sequence.
  automation_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&AutomationController::Context::DeleteInAutomationSequence,
                     context_));
}
