// Copyright (c) 2012 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 "content/browser/accessibility/browser_accessibility_manager_win.h"

#include <stddef.h>
#include <stdint.h>

#include <vector>

#include "base/command_line.h"
#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.h"
#include "content/browser/accessibility/browser_accessibility_event_win.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
#include "content/common/accessibility_messages.h"
#include "ui/base/win/atl_module.h"

namespace content {

// static
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
    const ui::AXTreeUpdate& initial_tree,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory) {
  return new BrowserAccessibilityManagerWin(initial_tree, delegate, factory);
}

BrowserAccessibilityManagerWin*
BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() {
  return static_cast<BrowserAccessibilityManagerWin*>(this);
}

BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin(
    const ui::AXTreeUpdate& initial_tree,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory)
    : BrowserAccessibilityManager(delegate, factory),
      load_complete_pending_(false) {
  ui::win::CreateATLModuleIfNeeded();
  Initialize(initial_tree);
  ui::GetIAccessible2UsageObserverList().AddObserver(this);
}

BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
  // Destroy the tree in the subclass, rather than in the inherited
  // destructor, otherwise our overrides of functions like
  // OnNodeWillBeDeleted won't be called.
  tree_.reset(NULL);
  ui::GetIAccessible2UsageObserverList().RemoveObserver(this);
}

// static
ui::AXTreeUpdate
    BrowserAccessibilityManagerWin::GetEmptyDocument() {
  ui::AXNodeData empty_document;
  empty_document.id = 0;
  empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA;
  empty_document.AddState(ui::AX_STATE_READ_ONLY);
  empty_document.AddState(ui::AX_STATE_BUSY);

  ui::AXTreeUpdate update;
  update.root_id = empty_document.id;
  update.nodes.push_back(empty_document);
  return update;
}

HWND BrowserAccessibilityManagerWin::GetParentHWND() {
  BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
  if (!delegate)
    return NULL;
  return delegate->AccessibilityGetAcceleratedWidget();
}

IAccessible* BrowserAccessibilityManagerWin::GetParentIAccessible() {
  BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
  if (!delegate)
    return NULL;
  return delegate->AccessibilityGetNativeViewAccessible();
}

void BrowserAccessibilityManagerWin::OnIAccessible2Used() {
  // When IAccessible2 APIs have been used elsewhere in the codebase,
  // enable basic web accessibility support. (Full screen reader support is
  // detected later when specific more advanced APIs are accessed.)
  BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
      AccessibilityMode::kNativeAPIs | AccessibilityMode::kWebContents);
}

void BrowserAccessibilityManagerWin::UserIsReloading() {
  if (GetRoot()) {
    (new BrowserAccessibilityEventWin(
        BrowserAccessibilityEvent::FromRenderFrameHost,
        ui::AX_EVENT_NONE,
        IA2_EVENT_DOCUMENT_RELOAD,
        GetRoot()))->Fire();
  }
}

BrowserAccessibility* BrowserAccessibilityManagerWin::GetFocus() {
  BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
  return GetActiveDescendant(focus);
}

void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
    BrowserAccessibilityEvent::Source source,
    ui::AXEvent event_type,
    BrowserAccessibility* node) {
  bool can_fire_events = CanFireEvents();

  // TODO(dmazzoni): A better fix would be to always have a HWND.
  // http://crbug.com/521877
  if (event_type == ui::AX_EVENT_LOAD_COMPLETE && can_fire_events)
    load_complete_pending_ = false;

  if (load_complete_pending_ && can_fire_events && GetRoot()) {
    load_complete_pending_ = false;
    NotifyAccessibilityEvent(BrowserAccessibilityEvent::FromPendingLoadComplete,
                             ui::AX_EVENT_LOAD_COMPLETE,
                             GetRoot());
  }

  if (!can_fire_events &&
      !load_complete_pending_ &&
      event_type == ui::AX_EVENT_LOAD_COMPLETE &&
      GetRoot() &&
      !GetRoot()->HasState(ui::AX_STATE_OFFSCREEN) &&
      GetRoot()->PlatformChildCount() > 0) {
    load_complete_pending_ = true;
  }

  if (event_type == ui::AX_EVENT_BLUR) {
    // Equivalent to focus on the root.
    event_type = ui::AX_EVENT_FOCUS;
    node = GetRoot();
  }

  if (event_type == ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED) {
    // Fire the event on the object where the focus of the selection is.
    int32_t focus_id = GetTreeData().sel_focus_object_id;
    BrowserAccessibility* focus_object = GetFromID(focus_id);
    if (focus_object) {
      (new BrowserAccessibilityEventWin(
          source,
          ui::AX_EVENT_NONE,
          IA2_EVENT_TEXT_CARET_MOVED,
          focus_object))->Fire();
      return;
    }
  }

  BrowserAccessibilityManager::NotifyAccessibilityEvent(
      source, event_type, node);
}

BrowserAccessibilityEvent::Result
    BrowserAccessibilityManagerWin::FireWinAccessibilityEvent(
        BrowserAccessibilityEventWin* event) {
  const BrowserAccessibility* target = event->target();
  ui::AXEvent event_type = event->event_type();
  LONG win_event_type = event->win_event_type();

  BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
  if (!root_delegate)
    return BrowserAccessibilityEvent::FailedBecauseFrameIsDetached;

  HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget();
  if (!hwnd)
    return BrowserAccessibilityEvent::FailedBecauseNoWindow;

  // Don't fire events when this document might be stale as the user has
  // started navigating to a new document.
  if (user_is_navigating_away_)
    return BrowserAccessibilityEvent::DiscardedBecauseUserNavigatingAway;

  // Inline text boxes are an internal implementation detail, we don't
  // expose them to Windows.
  if (target->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX)
    return BrowserAccessibilityEvent::NotNeededOnThisPlatform;

  if ((event_type == ui::AX_EVENT_LIVE_REGION_CREATED ||
       event_type == ui::AX_EVENT_LIVE_REGION_CHANGED) &&
      target->GetBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY)) {
    return BrowserAccessibilityEvent::DiscardedBecauseLiveRegionBusy;
  }

  if (!target)
    return BrowserAccessibilityEvent::FailedBecauseNoFocus;

  event->set_target(target);

  // It doesn't make sense to fire a REORDER event on a leaf node; that
  // happens when the target has internal children inline text boxes.
  if (win_event_type == EVENT_OBJECT_REORDER &&
      target->PlatformChildCount() == 0) {
    return BrowserAccessibilityEvent::NotNeededOnThisPlatform;
  }

  // Pass the negation of this node's unique id in the |child_id|
  // argument to NotifyWinEvent; the AT client will then call get_accChild
  // on the HWND's accessibility object and pass it that same id, which
  // we can use to retrieve the IAccessible for this node.
  LONG child_id = -target->unique_id();
  ::NotifyWinEvent(win_event_type, hwnd, OBJID_CLIENT, child_id);

  return BrowserAccessibilityEvent::Sent;
}

bool BrowserAccessibilityManagerWin::CanFireEvents() {
  BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
  if (!root_delegate)
    return false;
  HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget();
  return hwnd != nullptr;
}

void BrowserAccessibilityManagerWin::FireFocusEvent(
    BrowserAccessibilityEvent::Source source,
    BrowserAccessibility* node) {
  DCHECK(node);
  // On Windows, we always fire a FOCUS event on the root of a frame before
  // firing a focus event within that frame.
  if (node->manager() != last_focused_manager_ &&
      node != node->manager()->GetRoot()) {
    BrowserAccessibilityEvent::Create(source,
                                      ui::AX_EVENT_FOCUS,
                                      node->manager()->GetRoot())->Fire();
  }

  BrowserAccessibilityManager::FireFocusEvent(source, node);
}

gfx::Rect BrowserAccessibilityManagerWin::GetViewBounds() {
  // We have to take the device scale factor into account on Windows.
  BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
  if (delegate) {
    gfx::Rect bounds = delegate->AccessibilityGetViewBounds();
    if (device_scale_factor() > 0.0 && device_scale_factor() != 1.0)
      bounds = ScaleToEnclosingRect(bounds, device_scale_factor());
    return bounds;
  }
  return gfx::Rect();
}

void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
                                                   ui::AXNode* node) {
  DCHECK(node);
  BrowserAccessibilityManager::OnNodeCreated(tree, node);
  BrowserAccessibility* obj = GetFromAXNode(node);
  if (!obj)
    return;
  if (!obj->IsNative())
    return;
}

void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
    ui::AXTree* tree,
    bool root_changed,
    const std::vector<ui::AXTreeDelegate::Change>& changes) {
  BrowserAccessibilityManager::OnAtomicUpdateFinished(
      tree, root_changed, changes);

  // Do a sequence of Windows-specific updates on each node. Each one is
  // done in a single pass that must complete before the next step starts.
  // The first step moves win_attributes_ to old_win_attributes_ and then
  // recomputes all of win_attributes_ other than IAccessibleText.
  for (size_t i = 0; i < changes.size(); ++i) {
    const ui::AXNode* changed_node = changes[i].node;
    DCHECK(changed_node);
    BrowserAccessibility* obj = GetFromAXNode(changed_node);
    if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf())
      ToBrowserAccessibilityWin(obj)
          ->GetCOM()
          ->UpdateStep1ComputeWinAttributes();
  }

  // The next step updates the hypertext of each node, which is a
  // concatenation of all of its child text nodes, so it can't run until
  // the text of all of the nodes was computed in the previous step.
  for (size_t i = 0; i < changes.size(); ++i) {
    const ui::AXNode* changed_node = changes[i].node;
    DCHECK(changed_node);
    BrowserAccessibility* obj = GetFromAXNode(changed_node);
    if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf())
      ToBrowserAccessibilityWin(obj)->GetCOM()->UpdateStep2ComputeHypertext();
  }

  // The third step fires events on nodes based on what's changed - like
  // if the name, value, or description changed, or if the hypertext had
  // text inserted or removed. It's able to figure out exactly what changed
  // because we still have old_win_attributes_ populated.
  // This step has to run after the previous two steps complete because the
  // client may walk the tree when it receives any of these events.
  // At the end, it deletes old_win_attributes_ since they're not needed
  // anymore.
  for (size_t i = 0; i < changes.size(); ++i) {
    const ui::AXNode* changed_node = changes[i].node;
    DCHECK(changed_node);
    BrowserAccessibility* obj = GetFromAXNode(changed_node);
    if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) {
      ToBrowserAccessibilityWin(obj)->GetCOM()->UpdateStep3FireEvents(
          changes[i].type == AXTreeDelegate::SUBTREE_CREATED);
    }
  }
}

}  // namespace content
