// 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_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 = -(ToBrowserAccessibilityWin(target)->GetCOM()->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
