// Copyright (c) 2013 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 "win8/test/ui_automation_client.h"

#include <atlbase.h>
#include <atlcom.h>
#include <oleauto.h>
#include <stdint.h>
#include <uiautomation.h>

#include <algorithm>

#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"

namespace win8 {
namespace internal {

// The guts of the UI automation client which runs on a dedicated thread in the
// multi-threaded COM apartment. An instance may be constructed on any thread,
// but Initialize() must be invoked on a thread in the MTA.
class UIAutomationClient::Context {
 public:
  // Returns a new instance ready for initialization and use on another thread.
  static base::WeakPtr<Context> Create();

  // Deletes the instance.
  void DeleteOnAutomationThread();

  // Initializes the context, invoking |init_callback| via |client_runner| when
  // done. On success, |result_callback| will eventually be called after the
  // window has been processed. On failure, this instance self-destructs after
  // posting |init_callback|.
  void Initialize(
      scoped_refptr<base::SingleThreadTaskRunner> client_runner,
      base::string16 class_name,
      base::string16 item_name,
      UIAutomationClient::InitializedCallback init_callback,
      UIAutomationClient::ResultCallback result_callback);

  // Methods invoked by event handlers via weak pointers.
  void HandleAutomationEvent(
      base::win::ScopedComPtr<IUIAutomationElement> sender,
      EVENTID eventId);

 private:
  class EventHandler;

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

  HRESULT InstallWindowObserver();
  HRESULT RemoveWindowObserver();

  void HandleWindowOpen(
      const base::win::ScopedComPtr<IUIAutomationElement>& window);
  void ProcessWindow(
      const base::win::ScopedComPtr<IUIAutomationElement>& window);
  HRESULT InvokeDesiredItem(
      const base::win::ScopedComPtr<IUIAutomationElement>& element);
  HRESULT GetInvokableItems(
      const base::win::ScopedComPtr<IUIAutomationElement>& element,
      std::vector<base::string16>* choices);
  void CloseWindow(const base::win::ScopedComPtr<IUIAutomationElement>& window);

  base::ThreadChecker thread_checker_;

  // The loop on which the client itself lives.
  scoped_refptr<base::SingleThreadTaskRunner> client_runner_;

  // The class name of the window for which the client waits.
  base::string16 class_name_;

  // The name of the item to invoke.
  base::string16 item_name_;

  // The consumer's result callback.
  ResultCallback result_callback_;

  // The automation client.
  base::win::ScopedComPtr<IUIAutomation> automation_;

  // A handler of Window open events.
  base::win::ScopedComPtr<IUIAutomationEventHandler> event_handler_;

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

  DISALLOW_COPY_AND_ASSIGN(Context);
};

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

  EventHandler();
  virtual ~EventHandler();

  // Initializes the object with its parent UI automation client context's
  // message loop and pointer. Events are dispatched back to the context on
  // the given loop.
  void Initialize(
      const scoped_refptr<base::SingleThreadTaskRunner>& context_runner,
      const base::WeakPtr<UIAutomationClient::Context>& context);

  // IUIAutomationEventHandler methods.
  STDMETHOD(HandleAutomationEvent)(IUIAutomationElement* sender,
                                   EVENTID eventId) override;

 private:
  // The task runner for the UI automation client context.
  scoped_refptr<base::SingleThreadTaskRunner> context_runner_;

  // The parent UI automation client context.
  base::WeakPtr<UIAutomationClient::Context> context_;

  DISALLOW_COPY_AND_ASSIGN(EventHandler);
};

UIAutomationClient::Context::EventHandler::EventHandler() {}

UIAutomationClient::Context::EventHandler::~EventHandler() {}

void UIAutomationClient::Context::EventHandler::Initialize(
    const scoped_refptr<base::SingleThreadTaskRunner>& context_runner,
    const base::WeakPtr<UIAutomationClient::Context>& context) {
  context_runner_ = context_runner;
  context_ = context;
}

HRESULT UIAutomationClient::Context::EventHandler::HandleAutomationEvent(
    IUIAutomationElement* sender,
    EVENTID eventId) {
  // Event handlers are invoked on an arbitrary thread in the MTA. Send the
  // event back to the main UI automation thread for processing.
  context_runner_->PostTask(
      FROM_HERE,
      base::Bind(&UIAutomationClient::Context::HandleAutomationEvent, context_,
                 base::win::ScopedComPtr<IUIAutomationElement>(sender),
                 eventId));

  return S_OK;
}

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

void UIAutomationClient::Context::DeleteOnAutomationThread() {
  DCHECK(thread_checker_.CalledOnValidThread());
  delete this;
}

UIAutomationClient::Context::Context() : weak_ptr_factory_(this) {}

UIAutomationClient::Context::~Context() {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (event_handler_.get()) {
    event_handler_ = NULL;
    HRESULT result = automation_->RemoveAllEventHandlers();
    LOG_IF(ERROR, FAILED(result)) << std::hex << result;
  }
}

void UIAutomationClient::Context::Initialize(
    scoped_refptr<base::SingleThreadTaskRunner> client_runner,
    base::string16 class_name,
    base::string16 item_name,
    UIAutomationClient::InitializedCallback init_callback,
    UIAutomationClient::ResultCallback result_callback) {
  // This and all other methods must be called on the automation thread.
  DCHECK(!client_runner->BelongsToCurrentThread());
  // Bind the checker to this thread.
  thread_checker_.DetachFromThread();
  DCHECK(thread_checker_.CalledOnValidThread());

  client_runner_ = client_runner;
  class_name_ = class_name;
  item_name_ = item_name;
  result_callback_ = result_callback;

  HRESULT result = automation_.CreateInstance(CLSID_CUIAutomation, NULL,
                                              CLSCTX_INPROC_SERVER);
  if (FAILED(result) || !automation_.get())
    LOG(ERROR) << std::hex << result;
  else
    result = InstallWindowObserver();

  // Tell the client that initialization is complete.
  client_runner_->PostTask(FROM_HERE, base::Bind(init_callback, result));

  // Self-destruct if the overall operation failed.
  if (FAILED(result))
    delete this;
}

// Installs the window observer.
HRESULT UIAutomationClient::Context::InstallWindowObserver() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(automation_.get());
  DCHECK(!event_handler_.get());

  HRESULT result = S_OK;
  base::win::ScopedComPtr<IUIAutomationElement> root_element;
  base::win::ScopedComPtr<IUIAutomationCacheRequest> cache_request;

  // Observe the opening of all windows.
  result = automation_->GetRootElement(root_element.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  // Cache Window class, HWND, and window pattern for opened windows.
  result = automation_->CreateCacheRequest(cache_request.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }
  cache_request->AddProperty(UIA_ClassNamePropertyId);
  cache_request->AddProperty(UIA_NativeWindowHandlePropertyId);

  // Create the observer.
  CComObject<EventHandler>* event_handler_obj = NULL;
  result = CComObject<EventHandler>::CreateInstance(&event_handler_obj);
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }
  event_handler_obj->Initialize(base::ThreadTaskRunnerHandle::Get(),
                                weak_ptr_factory_.GetWeakPtr());
  base::win::ScopedComPtr<IUIAutomationEventHandler> event_handler(
      event_handler_obj);

  result = automation_->AddAutomationEventHandler(
      UIA_Window_WindowOpenedEventId, root_element.get(), TreeScope_Descendants,
      cache_request.get(), event_handler.get());

  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  event_handler_ = event_handler;
  return S_OK;
}

// Removes this instance's window observer.
HRESULT UIAutomationClient::Context::RemoveWindowObserver() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(automation_.get());
  DCHECK(event_handler_.get());

  HRESULT result = S_OK;
  base::win::ScopedComPtr<IUIAutomationElement> root_element;

  // The opening of all windows are observed.
  result = automation_->GetRootElement(root_element.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  result = automation_->RemoveAutomationEventHandler(
      UIA_Window_WindowOpenedEventId, root_element.get(), event_handler_.get());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  event_handler_ = NULL;
  return S_OK;
}

// Handles an automation event. If the event results in the processing for which
// this context was created, the context self-destructs after posting the
// results to the client.
void UIAutomationClient::Context::HandleAutomationEvent(
    base::win::ScopedComPtr<IUIAutomationElement> sender,
    EVENTID eventId) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (eventId == UIA_Window_WindowOpenedEventId)
    HandleWindowOpen(sender);
}

// Handles a WindowOpen event. If |window| is the one for which this instance is
// waiting, it is processed and this instance self-destructs after posting the
// results to the client.
void UIAutomationClient::Context::HandleWindowOpen(
    const base::win::ScopedComPtr<IUIAutomationElement>& window) {
  DCHECK(thread_checker_.CalledOnValidThread());
  HRESULT hr = S_OK;
  base::win::ScopedVariant var;

  hr = window->GetCachedPropertyValueEx(UIA_ClassNamePropertyId, TRUE,
                                        var.Receive());
  if (FAILED(hr)) {
    LOG(ERROR) << std::hex << hr;
    return;
  }

  if (V_VT(var.ptr()) != VT_BSTR) {
    LOG(ERROR) << __FUNCTION__
               << " class name is not a BSTR: " << V_VT(var.ptr());
    return;
  }

  base::string16 class_name(V_BSTR(var.ptr()));

  // Window class names are atoms, which are case-insensitive. Assume that
  // the window in question only needs ASCII case-insensitivity.
  if (class_name.size() == class_name_.size() &&
      std::equal(class_name.begin(), class_name.end(), class_name_.begin(),
                 base::CaseInsensitiveCompareASCII<wchar_t>())) {
    RemoveWindowObserver();
    ProcessWindow(window);
  }
}

// Processes |window| by invoking the desired child item. If the item cannot be
// found or invoked, an attempt is made to get a list of all invokable children.
// The results are posted back to the client on |client_runner_|, and this
// instance self-destructs.
void UIAutomationClient::Context::ProcessWindow(
    const base::win::ScopedComPtr<IUIAutomationElement>& window) {
  DCHECK(thread_checker_.CalledOnValidThread());

  HRESULT result = S_OK;
  std::vector<base::string16> choices;
  result = InvokeDesiredItem(window);
  if (FAILED(result)) {
    GetInvokableItems(window, &choices);
    CloseWindow(window);
  }

  client_runner_->PostTask(FROM_HERE,
                           base::Bind(result_callback_, result, choices));

  // Self-destruct since there's nothing more to be done here.
  delete this;
}

// Invokes the desired child of |element|.
HRESULT UIAutomationClient::Context::InvokeDesiredItem(
    const base::win::ScopedComPtr<IUIAutomationElement>& element) {
  DCHECK(thread_checker_.CalledOnValidThread());

  HRESULT result = S_OK;
  base::win::ScopedVariant var;
  base::win::ScopedComPtr<IUIAutomationCondition> invokable_condition;
  base::win::ScopedComPtr<IUIAutomationCondition> item_name_condition;
  base::win::ScopedComPtr<IUIAutomationCondition> control_view_condition;
  base::win::ScopedComPtr<IUIAutomationCondition> condition;
  base::win::ScopedComPtr<IUIAutomationCacheRequest> cache_request;
  base::win::ScopedComPtr<IUIAutomationElement> target;

  // Search for an invokable element named item_name.
  var.Set(true);
  result = automation_->CreatePropertyCondition(
      UIA_IsInvokePatternAvailablePropertyId,
      var,
      invokable_condition.Receive());
  var.Reset();
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  var.Set(item_name_.c_str());
  result = automation_->CreatePropertyCondition(UIA_NamePropertyId,
                                                var,
                                                item_name_condition.Receive());
  var.Reset();
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  result = automation_->get_ControlViewCondition(
      control_view_condition.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  std::vector<IUIAutomationCondition*> conditions;
  conditions.push_back(invokable_condition.get());
  conditions.push_back(item_name_condition.get());
  conditions.push_back(control_view_condition.get());
  result = automation_->CreateAndConditionFromNativeArray(
      &conditions[0], conditions.size(), condition.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  // Cache invokable pattern for the item.
  result = automation_->CreateCacheRequest(cache_request.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }
  cache_request->AddPattern(UIA_InvokePatternId);

  result = element->FindFirstBuildCache(
      static_cast<TreeScope>(TreeScope_Children | TreeScope_Descendants),
      condition.get(), cache_request.get(), target.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  // If the item was found, invoke it.
  if (!target.get()) {
    LOG(WARNING) << "Failed to find desired item to invoke.";
    return E_FAIL;
  }

  base::win::ScopedComPtr<IUIAutomationInvokePattern> invoker;
  result = target->GetCachedPatternAs(UIA_InvokePatternId, invoker.iid(),
                                      invoker.ReceiveVoid());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  result = invoker->Invoke();
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  return S_OK;
}

// Populates |choices| with the names of all invokable children of |element|.
HRESULT UIAutomationClient::Context::GetInvokableItems(
    const base::win::ScopedComPtr<IUIAutomationElement>& element,
    std::vector<base::string16>* choices) {
  DCHECK(choices);
  DCHECK(thread_checker_.CalledOnValidThread());

  HRESULT result = S_OK;
  base::win::ScopedVariant var;
  base::win::ScopedComPtr<IUIAutomationCondition> invokable_condition;
  base::win::ScopedComPtr<IUIAutomationCondition> control_view_condition;
  base::win::ScopedComPtr<IUIAutomationCondition> condition;
  base::win::ScopedComPtr<IUIAutomationCacheRequest> cache_request;
  base::win::ScopedComPtr<IUIAutomationElementArray> element_array;
  base::win::ScopedComPtr<IUIAutomationElement> child_element;

  // Search for all invokable elements.
  var.Set(true);
  result = automation_->CreatePropertyCondition(
      UIA_IsInvokePatternAvailablePropertyId,
      var,
      invokable_condition.Receive());
  var.Reset();
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  result = automation_->get_ControlViewCondition(
      control_view_condition.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  result = automation_->CreateAndCondition(invokable_condition.get(),
                                           control_view_condition.get(),
                                           condition.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  // Cache item names.
  result = automation_->CreateCacheRequest(cache_request.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }
  cache_request->AddProperty(UIA_NamePropertyId);

  result = element->FindAllBuildCache(
      static_cast<TreeScope>(TreeScope_Children | TreeScope_Descendants),
      condition.get(), cache_request.get(), element_array.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  if (!element_array.get()) {
    LOG(ERROR) << "The window may have vanished.";
    return S_OK;
  }

  int num_elements = 0;
  result = element_array->get_Length(&num_elements);
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return result;
  }

  choices->clear();
  choices->reserve(num_elements);
  for (int i = 0; i < num_elements; ++i) {
    child_element.Release();
    result = element_array->GetElement(i, child_element.Receive());
    if (FAILED(result)) {
      LOG(ERROR) << std::hex << result;
      continue;
    }
    result = child_element->GetCachedPropertyValueEx(UIA_NamePropertyId, TRUE,
                                                     var.Receive());
    if (FAILED(result)) {
      LOG(ERROR) << std::hex << result;
      continue;
    }
    if (V_VT(var.ptr()) != VT_BSTR) {
      LOG(ERROR) << __FUNCTION__ << " name is not a BSTR: " << V_VT(var.ptr());
      continue;
    }
    choices->push_back(base::string16(V_BSTR(var.ptr())));
    var.Reset();
  }

  return result;
}

// Closes the element |window| by sending it an escape key.
void UIAutomationClient::Context::CloseWindow(
    const base::win::ScopedComPtr<IUIAutomationElement>& window) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // It's tempting to get the Window pattern from |window| and invoke its Close
  // method. Unfortunately, this doesn't work. Sending an escape key does the
  // trick, though.
  HRESULT result = S_OK;
  base::win::ScopedVariant var;

  result = window->GetCachedPropertyValueEx(
      UIA_NativeWindowHandlePropertyId,
      TRUE,
      var.Receive());
  if (FAILED(result)) {
    LOG(ERROR) << std::hex << result;
    return;
  }

  if (V_VT(var.ptr()) != VT_I4) {
    LOG(ERROR) << __FUNCTION__
               << " window handle is not an int: " << V_VT(var.ptr());
    return;
  }

  HWND handle = reinterpret_cast<HWND>(V_I4(var.ptr()));

  uint32_t scan_code = MapVirtualKey(VK_ESCAPE, MAPVK_VK_TO_VSC);
  PostMessage(handle, WM_KEYDOWN, VK_ESCAPE,
              MAKELPARAM(1, scan_code));
  PostMessage(handle, WM_KEYUP, VK_ESCAPE,
              MAKELPARAM(1, scan_code | KF_REPEAT | KF_UP));
}

UIAutomationClient::UIAutomationClient()
    : automation_thread_("UIAutomation") {}

UIAutomationClient::~UIAutomationClient() {
  DCHECK(thread_checker_.CalledOnValidThread());

  // context_ is still valid when the caller destroys the instance before the
  // callback(s) have fired. In this case, delete the context on the automation
  // thread before joining with it.
  automation_thread_.message_loop()->PostTask(
      FROM_HERE,
      base::Bind(&UIAutomationClient::Context::DeleteOnAutomationThread,
                 context_));
}

void UIAutomationClient::Begin(const wchar_t* class_name,
                               const base::string16& item_name,
                               const InitializedCallback& init_callback,
                               const ResultCallback& result_callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(context_.get(), static_cast<Context*>(NULL));

  // Start the automation thread and initialize our automation client on it.
  context_ = Context::Create();
  automation_thread_.init_com_with_mta(true);
  automation_thread_.Start();
  automation_thread_.message_loop()->PostTask(
      FROM_HERE,
      base::Bind(&UIAutomationClient::Context::Initialize,
                 context_,
                 base::ThreadTaskRunnerHandle::Get(),
                 base::string16(class_name),
                 item_name,
                 init_callback,
                 result_callback));
}

}  // namespace internal
}  // namespace win8
