// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

/**
 * @fileoverview DOM manipulation and querying routines.
 */

goog.provide('bot.dom');

goog.require('bot');
goog.require('bot.color');
goog.require('bot.dom.core');
goog.require('bot.locators.css');
goog.require('bot.userAgent');
goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.DomHelper');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.TagName');
goog.require('goog.math');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Rect');
goog.require('goog.string');
goog.require('goog.style');
goog.require('goog.userAgent');


/**
 * Whether Shadow DOM operations are supported by the browser.
 * @const {boolean}
 */
bot.dom.IS_SHADOW_DOM_ENABLED = (typeof ShadowRoot === 'function');


/**
 * Retrieves the active element for a node's owner document.
 * @param {(!Node|!Window)} nodeOrWindow The node whose owner document to get
 *     the active element for.
 * @return {?Element} The active element, if any.
 */
bot.dom.getActiveElement = function (nodeOrWindow) {
  var active = goog.dom.getActiveElement(
    goog.dom.getOwnerDocument(nodeOrWindow));
  // IE has the habit of returning an empty object from
  // goog.dom.getActiveElement instead of null.
  if (goog.userAgent.IE &&
    active &&
    typeof active.nodeType === 'undefined') {
    return null;
  }
  return active;
};


/**
 * @const
 */
bot.dom.isElement = bot.dom.core.isElement;


/**
 * Returns whether an element is in an interactable state: whether it is shown
 * to the user, ignoring its opacity, and whether it is enabled.
 *
 * @param {!Element} element The element to check.
 * @return {boolean} Whether the element is interactable.
 * @see bot.dom.isShown.
 * @see bot.dom.isEnabled
 */
bot.dom.isInteractable = function (element) {
  return bot.dom.isShown(element, /*ignoreOpacity=*/true) &&
    bot.dom.isEnabled(element) &&
    !bot.dom.hasPointerEventsDisabled_(element);
};


/**
 * @param {!Element} element Element.
 * @return {boolean} Whether element is set by the CSS pointer-events property
 *     not to be interactable.
 * @private
 */
bot.dom.hasPointerEventsDisabled_ = function (element) {
  if (goog.userAgent.IE ||
    (goog.userAgent.GECKO && !bot.userAgent.isEngineVersion('1.9.2'))) {
    // Don't support pointer events
    return false;
  }
  return bot.dom.getEffectiveStyle(element, 'pointer-events') == 'none';
};


/**
 * @const
 */
bot.dom.isSelectable = bot.dom.core.isSelectable;


/**
 * @const
 */
bot.dom.isSelected = bot.dom.core.isSelected;


/**
 * List of the focusable fields, according to
 * http://www.w3.org/TR/html401/interact/scripts.html#adef-onfocus
 * @private {!Array.<!goog.dom.TagName>}
 * @const
 */
bot.dom.FOCUSABLE_FORM_FIELDS_ = [
  goog.dom.TagName.A,
  goog.dom.TagName.AREA,
  goog.dom.TagName.BUTTON,
  goog.dom.TagName.INPUT,
  goog.dom.TagName.LABEL,
  goog.dom.TagName.SELECT,
  goog.dom.TagName.TEXTAREA
];


/**
 * Returns whether a node is a focusable element.  An element may receive focus
 * if it is a form field, has a non-negative tabindex, or is editable.
 * @param {!Element} element The node to test.
 * @return {boolean} Whether the node is focusable.
 */
bot.dom.isFocusable = function (element) {
  return goog.array.some(bot.dom.FOCUSABLE_FORM_FIELDS_, tagNameMatches) ||
    (bot.dom.getAttribute(element, 'tabindex') != null &&
      Number(bot.dom.getProperty(element, 'tabIndex')) >= 0) ||
    bot.dom.isEditable(element);

  function tagNameMatches(tagName) {
    return bot.dom.isElement(element, tagName);
  }
};


/**
 * @const
 */
bot.dom.getProperty = bot.dom.core.getProperty;


/**
 * @const
 */
bot.dom.getAttribute = bot.dom.core.getAttribute;


/**
 * List of elements that support the "disabled" attribute, as defined by the
 * HTML 4.01 specification.
 * @private {!Array.<!goog.dom.TagName>}
 * @const
 * @see http://www.w3.org/TR/html401/interact/forms.html#h-17.12.1
 */
bot.dom.DISABLED_ATTRIBUTE_SUPPORTED_ = [
  goog.dom.TagName.BUTTON,
  goog.dom.TagName.INPUT,
  goog.dom.TagName.OPTGROUP,
  goog.dom.TagName.OPTION,
  goog.dom.TagName.SELECT,
  goog.dom.TagName.TEXTAREA
];


/**
 * Determines if an element is enabled. An element is considered enabled if it
 * does not support the "disabled" attribute, or if it is not disabled.
 * @param {!Element} el The element to test.
 * @return {boolean} Whether the element is enabled.
 */
bot.dom.isEnabled = function (el) {
  var isSupported = goog.array.some(
    bot.dom.DISABLED_ATTRIBUTE_SUPPORTED_,
    function (tagName) { return bot.dom.isElement(el, tagName); });
  if (!isSupported) {
    return true;
  }

  if (bot.dom.getProperty(el, 'disabled')) {
    return false;
  }

  // The element is not explicitly disabled, but if it is an OPTION or OPTGROUP,
  // we must test if it inherits its state from a parent.
  if (el.parentNode &&
    el.parentNode.nodeType == goog.dom.NodeType.ELEMENT &&
    bot.dom.isElement(el, goog.dom.TagName.OPTGROUP) ||
    bot.dom.isElement(el, goog.dom.TagName.OPTION)) {
    return bot.dom.isEnabled(/**@type{!Element}*/(el.parentNode));
  }

  // Is there an ancestor of the current element that is a disabled fieldset
  // and whose child is also an ancestor-or-self of the current element but is
  // not the first legend child of the fieldset. If so then the element is
  // disabled.
  return !goog.dom.getAncestor(el, function (e) {
    var parent = e.parentNode;

    if (parent &&
      bot.dom.isElement(parent, goog.dom.TagName.FIELDSET) &&
      bot.dom.getProperty(/** @type {!Element} */(parent), 'disabled')) {
      if (!bot.dom.isElement(e, goog.dom.TagName.LEGEND)) {
        return true;
      }

      var sibling = e;
      // Are there any previous legend siblings? If so then we are not the
      // first and the element is disabled
      while (sibling = goog.dom.getPreviousElementSibling(sibling)) {
        if (bot.dom.isElement(sibling, goog.dom.TagName.LEGEND)) {
          return true;
        }
      }
    }
    return false;
  }, true);
};


/**
 * List of input types that create text fields.
 * @private {!Array.<string>}
 * @const
 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#attr-input-type
 */
bot.dom.TEXTUAL_INPUT_TYPES_ = [
  'text',
  'search',
  'tel',
  'url',
  'email',
  'password',
  'number'
];


/**
 * TODO: Add support for designMode elements.
 *
 * @param {!Element} element The element to check.
 * @return {boolean} Whether the element accepts user-typed text.
 */
bot.dom.isTextual = function (element) {
  if (bot.dom.isElement(element, goog.dom.TagName.TEXTAREA)) {
    return true;
  }

  if (bot.dom.isElement(element, goog.dom.TagName.INPUT)) {
    var type = element.type.toLowerCase();
    return goog.array.contains(bot.dom.TEXTUAL_INPUT_TYPES_, type);
  }

  if (bot.dom.isContentEditable(element)) {
    return true;
  }

  return false;
};


/**
 * @param {!Element} element The element to check.
 * @return {boolean} Whether the element is a file input.
 */
bot.dom.isFileInput = function (element) {
  if (bot.dom.isElement(element, goog.dom.TagName.INPUT)) {
    var type = element.type.toLowerCase();
    return type == 'file';
  }

  return false;
};


/**
 * @param {!Element} element The element to check.
 * @param {string} inputType The type of input to check.
 * @return {boolean} Whether the element is an input with specified type.
 */
bot.dom.isInputType = function (element, inputType) {
  if (bot.dom.isElement(element, goog.dom.TagName.INPUT)) {
    var type = element.type.toLowerCase();
    return type == inputType;
  }

  return false;
};


/**
 * @param {!Element} element The element to check.
 * @return {boolean} Whether the element is contentEditable.
 */
bot.dom.isContentEditable = function (element) {
  // Check if browser supports contentEditable.
  if (element['contentEditable'] === undefined) {
    return false;
  }

  // Checking the element's isContentEditable property is preferred except for
  // IE where that property is not reliable on IE versions 7, 8, and 9.
  if (!goog.userAgent.IE && element['isContentEditable'] !== undefined) {
    return element.isContentEditable;
  }

  // For IE and for browsers where contentEditable is supported but
  // isContentEditable is not, traverse up the ancestors:
  function legacyIsContentEditable(e) {
    if (e.contentEditable == 'inherit') {
      var parent = bot.dom.getParentElement(e);
      return parent ? legacyIsContentEditable(parent) : false;
    } else {
      return e.contentEditable == 'true';
    }
  }
  return legacyIsContentEditable(element);
};


/**
 * TODO: Merge isTextual into this function and move to bot.dom.
 * For Puppet, requires adding support to getVisibleText for grabbing
 * text from all textual elements.
 *
 * Whether the element may contain text the user can edit.
 *
 * @param {!Element} element The element to check.
 * @return {boolean} Whether the element accepts user-typed text.
 */
bot.dom.isEditable = function (element) {
  return (bot.dom.isTextual(element) ||
    bot.dom.isFileInput(element) ||
    bot.dom.isInputType(element, 'range') ||
    bot.dom.isInputType(element, 'date') ||
    bot.dom.isInputType(element, 'month') ||
    bot.dom.isInputType(element, 'week') ||
    bot.dom.isInputType(element, 'time') ||
    bot.dom.isInputType(element, 'datetime-local') ||
    bot.dom.isInputType(element, 'color')) &&
    !bot.dom.getProperty(element, 'readOnly');
};


/**
 * Returns the parent element of the given node, or null. This is required
 * because the parent node may not be another element.
 *
 * @param {!Node} node The node who's parent is desired.
 * @return {Element} The parent element, if available, null otherwise.
 */
bot.dom.getParentElement = function (node) {
  var elem = node.parentNode;

  while (elem &&
    elem.nodeType != goog.dom.NodeType.ELEMENT &&
    elem.nodeType != goog.dom.NodeType.DOCUMENT &&
    elem.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) {
    elem = elem.parentNode;
  }
  return /** @type {Element} */ (bot.dom.isElement(elem) ? elem : null);
};


/**
 * Retrieves an explicitly-set, inline style value of an element. This returns
 * '' if there isn't a style attribute on the element or if this style property
 * has not been explicitly set in script.
 *
 * @param {!Element} elem Element to get the style value from.
 * @param {string} styleName Name of the style property in selector-case.
 * @return {string} The value of the style property.
 */
bot.dom.getInlineStyle = function (elem, styleName) {
  return goog.style.getStyle(elem, styleName);
};


/**
 * Retrieves the implicitly-set, effective style of an element, or null if it is
 * unknown. It returns the computed style where available; otherwise it looks
 * up the DOM tree for the first style value not equal to 'inherit,' using the
 * IE currentStyle of each node if available, and otherwise the inline style.
 * Since the computed, current, and inline styles can be different, the return
 * value of this function is not always consistent across browsers. See:
 * http://code.google.com/p/doctype/wiki/ArticleComputedStyleVsCascadedStyle
 *
 * @param {!Element} elem Element to get the style value from.
 * @param {string} propertyName Name of the CSS property.
 * @return {?string} The value of the style property, or null.
 */
bot.dom.getEffectiveStyle = function (elem, propertyName) {
  var styleName = goog.string.toCamelCase(propertyName);
  if (styleName == 'float' ||
    styleName == 'cssFloat' ||
    styleName == 'styleFloat') {
    styleName = bot.userAgent.IE_DOC_PRE9 ? 'styleFloat' : 'cssFloat';
  }
  var style = goog.style.getComputedStyle(elem, styleName) ||
    bot.dom.getCascadedStyle_(elem, styleName);
  if (style === null) {
    return null;
  }
  return bot.color.standardizeColor(styleName, style);
};


/**
 * Looks up the DOM tree for the first style value not equal to 'inherit,' using
 * the currentStyle of each node if available, and otherwise the inline style.
 *
 * @param {!Element} elem Element to get the style value from.
 * @param {string} styleName CSS style property in camelCase.
 * @return {?string} The value of the style property, or null.
 * @private
 */
bot.dom.getCascadedStyle_ = function (elem, styleName) {
  var style = elem.currentStyle || elem.style;
  var value = style[styleName];
  if (value === undefined && typeof style.getPropertyValue === 'function') {
    value = style.getPropertyValue(styleName);
  }

  if (value != 'inherit') {
    return value !== undefined ? value : null;
  }
  var parent = bot.dom.getParentElement(elem);
  return parent ? bot.dom.getCascadedStyle_(parent, styleName) : null;
};


/**
 * Extracted code from bot.dom.isShown.
 *
 * @param {!Element} elem The element to consider.
 * @param {boolean} ignoreOpacity Whether to ignore the element's opacity
 *     when determining whether it is shown.
 * @param {function(!Element):boolean} displayedFn a function that's used
 *     to tell if the chain of ancestors or descendants are all shown.
 * @return {boolean} Whether or not the element is visible.
 * @private
 */
bot.dom.isShown_ = function (elem, ignoreOpacity, displayedFn) {
  if (!bot.dom.isElement(elem)) {
    throw new Error('Argument to isShown must be of type Element');
  }

  // By convention, BODY element is always shown: BODY represents the document
  // and even if there's nothing rendered in there, user can always see there's
  // the document.
  if (bot.dom.isElement(elem, goog.dom.TagName.BODY)) {
    return true;
  }

  // Option or optgroup is shown iff enclosing select is shown (ignoring the
  // select's opacity).
  if (bot.dom.isElement(elem, goog.dom.TagName.OPTION) ||
    bot.dom.isElement(elem, goog.dom.TagName.OPTGROUP)) {
    var select = /**@type {Element}*/ (goog.dom.getAncestor(elem, function (e) {
      return bot.dom.isElement(e, goog.dom.TagName.SELECT);
    }));
    return !!select && bot.dom.isShown_(select, true, displayedFn);
  }

  // Image map elements are shown if image that uses it is shown, and
  // the area of the element is positive.
  var imageMap = bot.dom.maybeFindImageMap_(elem);
  if (imageMap) {
    return !!imageMap.image &&
      imageMap.rect.width > 0 && imageMap.rect.height > 0 &&
      bot.dom.isShown_(
        imageMap.image, ignoreOpacity, displayedFn);
  }

  // Any hidden input is not shown.
  if (bot.dom.isElement(elem, goog.dom.TagName.INPUT) &&
    elem.type.toLowerCase() == 'hidden') {
    return false;
  }

  // Any NOSCRIPT element is not shown.
  if (bot.dom.isElement(elem, goog.dom.TagName.NOSCRIPT)) {
    return false;
  }

  // Any element with hidden/collapsed visibility is not shown.
  var visibility = bot.dom.getEffectiveStyle(elem, 'visibility');
  if (visibility == 'collapse' || visibility == 'hidden') {
    return false;
  }

  if (!displayedFn(elem)) {
    return false;
  }

  // Any transparent element is not shown.
  if (!ignoreOpacity && bot.dom.getOpacity(elem) == 0) {
    return false;
  }

  // Any element without positive size dimensions is not shown.
  function positiveSize(e) {
    var rect = bot.dom.getClientRect(e);
    if (rect.height > 0 && rect.width > 0) {
      return true;
    }
    // A vertical or horizontal SVG Path element will report zero width or
    // height but is "shown" if it has a positive stroke-width.
    if (bot.dom.isElement(e, 'PATH') && (rect.height > 0 || rect.width > 0)) {
      var strokeWidth = bot.dom.getEffectiveStyle(e, 'stroke-width');
      return !!strokeWidth && (parseInt(strokeWidth, 10) > 0);
    }

    // Any element with hidden/collapsed visibility is not shown.
    var visibility = bot.dom.getEffectiveStyle(e, 'visibility');
    if (visibility == 'collapse' || visibility == 'hidden') {
      return false;
    }

    if (!displayedFn(e)) {
      return false;
    }
    // Zero-sized elements should still be considered to have positive size
    // if they have a child element or text node with positive size, unless
    // the element has an 'overflow' style of 'hidden'.
    // Note: Text nodes containing only structural whitespace (with newlines
    // or tabs) are ignored as they are likely just HTML formatting, not
    // visible content.
    return bot.dom.getEffectiveStyle(e, 'overflow') != 'hidden' &&
      goog.array.some(e.childNodes, function (n) {
        if (n.nodeType == goog.dom.NodeType.TEXT) {
          var text = n.nodeValue;
          // Ignore text nodes that are purely structural whitespace
          // (contain newlines or tabs and nothing else besides spaces)
          if (/^[\s]*$/.test(text) && /[\n\r\t]/.test(text)) {
            return false;
          }
          return true;
        }
        return bot.dom.isElement(n) && positiveSize(n);
      });
  }
  if (!positiveSize(elem)) {
    return false;
  }

  // Elements that are hidden by overflow are not shown.
  function hiddenByOverflow(e) {
    return bot.dom.getOverflowState(e) == bot.dom.OverflowState.HIDDEN &&
      goog.array.every(e.childNodes, function (n) {
        return !bot.dom.isElement(n) || hiddenByOverflow(n) ||
          !positiveSize(n);
      });
  }
  return !hiddenByOverflow(elem);
};


/**
 * Determines whether an element is what a user would call "shown". This means
 * that the element is shown in the viewport of the browser, and only has
 * height and width greater than 0px, and that its visibility is not "hidden"
 * and its display property is not "none".
 * Options and Optgroup elements are treated as special cases: they are
 * considered shown iff they have a enclosing select element that is shown.
 *
 * Elements in Shadow DOMs with younger shadow roots are not visible, and
 * elements distributed into shadow DOMs check the visibility of the
 * ancestors in the Composed DOM, rather than their ancestors in the logical
 * DOM.
 *
 * @param {!Element} elem The element to consider.
 * @param {boolean=} opt_ignoreOpacity Whether to ignore the element's opacity
 *     when determining whether it is shown; defaults to false.
 * @return {boolean} Whether or not the element is visible.
 */
bot.dom.isShown = function (elem, opt_ignoreOpacity) {
  /**
   * Determines whether an element or its parents have `display: none` or similar CSS properties set
   * @param {!Node} e the element
   * @return {!boolean}
   */
  function displayed(e) {
    if (bot.dom.isElement(e)) {
      var elem = /** @type {!Element} */ (e);
      if ((bot.dom.getEffectiveStyle(elem, 'display') == 'none')
        || (bot.dom.getEffectiveStyle(elem, 'content-visibility') == 'hidden')) {
        return false;
      }
    }

    var parent = bot.dom.getParentNodeInComposedDom(e);

    if (bot.dom.IS_SHADOW_DOM_ENABLED && (parent instanceof ShadowRoot)) {
      if (parent.host.shadowRoot && parent.host.shadowRoot !== parent) {
        // There is a younger shadow root, which will take precedence over
        // the shadow this element is in, thus this element won't be
        // displayed.
        return false;
      } else {
        parent = parent.host;
      }
    }

    if (parent && (parent.nodeType == goog.dom.NodeType.DOCUMENT ||
      parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT)) {
      return true;
    }

    // Child of DETAILS element is not shown unless the DETAILS element is open
    // or the child is a SUMMARY element.
    if (parent && bot.dom.isElement(parent, goog.dom.TagName.DETAILS) &&
      !parent.open && !bot.dom.isElement(e, goog.dom.TagName.SUMMARY)) {
      return false;
    }

    return !!parent && displayed(parent);
  }

  return bot.dom.isShown_(elem, !!opt_ignoreOpacity, displayed);
};


/**
 * The kind of overflow area in which an element may be located. NONE if it does
 * not overflow any ancestor element; HIDDEN if it overflows and cannot be
 * scrolled into view; SCROLL if it overflows but can be scrolled into view.
 *
 * @enum {string}
 */
bot.dom.OverflowState = {
  NONE: 'none',
  HIDDEN: 'hidden',
  SCROLL: 'scroll'
};


/**
 * Returns the overflow state of the given element.
 *
 * If an optional coordinate or rectangle region is provided, returns the
 * overflow state of that region relative to the element. A coordinate is
 * treated as a 1x1 rectangle whose top-left corner is the coordinate.
 *
 * @param {!Element} elem Element.
 * @param {!(goog.math.Coordinate|goog.math.Rect)=} opt_region
 *     Coordinate or rectangle relative to the top-left corner of the element.
 * @return {bot.dom.OverflowState} Overflow state of the element.
 */
bot.dom.getOverflowState = function (elem, opt_region) {
  var region = bot.dom.getClientRegion(elem, opt_region);
  var ownerDoc = goog.dom.getOwnerDocument(elem);
  var htmlElem = ownerDoc.documentElement;
  var bodyElem = ownerDoc.body;
  var htmlOverflowStyle = bot.dom.getEffectiveStyle(htmlElem, 'overflow');
  var treatAsFixedPosition;

  // Return the closest ancestor that the given element may overflow.
  function getOverflowParent(e) {
    var position = bot.dom.getEffectiveStyle(e, 'position');
    if (position == 'fixed') {
      treatAsFixedPosition = true;
      // Fixed-position element may only overflow the viewport.
      return e == htmlElem ? null : htmlElem;
    } else {
      var parent = bot.dom.getParentElement(e);
      while (parent && !canBeOverflowed(parent)) {
        parent = bot.dom.getParentElement(parent);
      }
      return parent;
    }

    function canBeOverflowed(container) {
      // The HTML element can always be overflowed.
      if (container == htmlElem) {
        return true;
      }
      // An element cannot overflow an element with an inline or contents display style.
      var containerDisplay = /** @type {string} */ (
        bot.dom.getEffectiveStyle(container, 'display'));
      if (goog.string.startsWith(containerDisplay, 'inline') ||
        (containerDisplay == 'contents')) {
        return false;
      }
      // An absolute-positioned element cannot overflow a static-positioned one.
      if (position == 'absolute' &&
        bot.dom.getEffectiveStyle(container, 'position') == 'static') {
        return false;
      }
      return true;
    }
  }

  // Return the x and y overflow styles for the given element.
  function getOverflowStyles(e) {
    // When the <html> element has an overflow style of 'visible', it assumes
    // the overflow style of the body, and the body is really overflow:visible.
    var overflowElem = e;
    if (htmlOverflowStyle == 'visible') {
      // Note: bodyElem will be null/undefined in SVG documents.
      if (e == htmlElem && bodyElem) {
        overflowElem = bodyElem;
      } else if (e == bodyElem) {
        return { x: 'visible', y: 'visible' };
      }
    }
    var overflow = {
      x: bot.dom.getEffectiveStyle(overflowElem, 'overflow-x'),
      y: bot.dom.getEffectiveStyle(overflowElem, 'overflow-y')
    };
    // The <html> element cannot have a genuine 'visible' overflow style,
    // because the viewport can't expand; 'visible' is really 'auto'.
    if (e == htmlElem) {
      overflow.x = overflow.x == 'visible' ? 'auto' : overflow.x;
      overflow.y = overflow.y == 'visible' ? 'auto' : overflow.y;
    }
    return overflow;
  }

  // Returns the scroll offset of the given element.
  function getScroll(e) {
    if (e == htmlElem) {
      return new goog.dom.DomHelper(ownerDoc).getDocumentScroll();
    } else {
      return new goog.math.Coordinate(e.scrollLeft, e.scrollTop);
    }
  }

  // Check if the element overflows any ancestor element.
  for (var container = getOverflowParent(elem);
    !!container;
    container = getOverflowParent(container)) {
    var containerOverflow = getOverflowStyles(container);

    // If the container has overflow:visible, the element cannot overflow it.
    if (containerOverflow.x == 'visible' && containerOverflow.y == 'visible') {
      continue;
    }

    var containerRect = bot.dom.getClientRect(container);

    // Zero-sized containers without overflow:visible hide all descendants.
    if (containerRect.width == 0 || containerRect.height == 0) {
      return bot.dom.OverflowState.HIDDEN;
    }

    // Check "underflow": if an element is to the left or above the container
    var underflowsX = region.right < containerRect.left;
    var underflowsY = region.bottom < containerRect.top;
    if ((underflowsX && containerOverflow.x == 'hidden') ||
      (underflowsY && containerOverflow.y == 'hidden')) {
      return bot.dom.OverflowState.HIDDEN;
    } else if ((underflowsX && containerOverflow.x != 'visible') ||
      (underflowsY && containerOverflow.y != 'visible')) {
      // When the element is positioned to the left or above a container, we
      // have to distinguish between the element being completely outside the
      // container and merely scrolled out of view within the container.
      var containerScroll = getScroll(container);
      var unscrollableX = region.right < containerRect.left - containerScroll.x;
      var unscrollableY = region.bottom < containerRect.top - containerScroll.y;
      if ((unscrollableX && containerOverflow.x != 'visible') ||
        (unscrollableY && containerOverflow.x != 'visible')) {
        return bot.dom.OverflowState.HIDDEN;
      }
      var containerState = bot.dom.getOverflowState(container);
      return containerState == bot.dom.OverflowState.HIDDEN ?
        bot.dom.OverflowState.HIDDEN : bot.dom.OverflowState.SCROLL;
    }

    // Check "overflow": if an element is to the right or below a container
    var overflowsX = region.left >= containerRect.left + containerRect.width;
    var overflowsY = region.top >= containerRect.top + containerRect.height;
    if ((overflowsX && containerOverflow.x == 'hidden') ||
      (overflowsY && containerOverflow.y == 'hidden')) {
      return bot.dom.OverflowState.HIDDEN;
    } else if ((overflowsX && containerOverflow.x != 'visible') ||
      (overflowsY && containerOverflow.y != 'visible')) {
      // If the element has fixed position and falls outside the scrollable area
      // of the document, then it is hidden.
      if (treatAsFixedPosition) {
        var docScroll = getScroll(container);
        if ((region.left >= htmlElem.scrollWidth - docScroll.x) ||
          (region.right >= htmlElem.scrollHeight - docScroll.y)) {
          return bot.dom.OverflowState.HIDDEN;
        }
      }
      // If the element can be scrolled into view of the parent, it has a scroll
      // state; unless the parent itself is entirely hidden by overflow, in
      // which it is also hidden by overflow.
      var containerState = bot.dom.getOverflowState(container);
      return containerState == bot.dom.OverflowState.HIDDEN ?
        bot.dom.OverflowState.HIDDEN : bot.dom.OverflowState.SCROLL;
    }
  }

  // Does not overflow any ancestor.
  return bot.dom.OverflowState.NONE;
};


/**
 * A regular expression to match the CSS transform matrix syntax.
 * @private {!RegExp}
 * @const
 */
bot.dom.CSS_TRANSFORM_MATRIX_REGEX_ =
  new RegExp('matrix\\(([\\d\\.\\-]+), ([\\d\\.\\-]+), ' +
    '([\\d\\.\\-]+), ([\\d\\.\\-]+), ' +
    '([\\d\\.\\-]+)(?:px)?, ([\\d\\.\\-]+)(?:px)?\\)');


/**
 * Gets the client rectangle of the DOM element. It often returns the same value
 * as Element.getBoundingClientRect, but is "fixed" for various scenarios:
 * 1. Like goog.style.getClientPosition, it adjusts for the inset border in IE.
 * 2. Gets a rect for <map>'s and <area>'s relative to the image using them.
 * 3. Gets a rect for SVG elements representing their true bounding box.
 * 4. Defines the client rect of the <html> element to be the window viewport.
 *
 * @param {!Element} elem The element to use.
 * @return {!goog.math.Rect} The interaction box of the element.
 */
bot.dom.getClientRect = function (elem) {
  var imageMap = bot.dom.maybeFindImageMap_(elem);
  if (imageMap) {
    return imageMap.rect;
  } else if (bot.dom.isElement(elem, goog.dom.TagName.HTML)) {
    // Define the client rect of the <html> element to be the viewport.
    var doc = goog.dom.getOwnerDocument(elem);
    var viewportSize = goog.dom.getViewportSize(goog.dom.getWindow(doc));
    return new goog.math.Rect(0, 0, viewportSize.width, viewportSize.height);
  } else {
    var nativeRect;
    try {
      // TODO: in IE and Firefox, getBoundingClientRect includes stroke width,
      // but getBBox does not.
      nativeRect = elem.getBoundingClientRect();
    } catch (e) {
      // On IE < 9, calling getBoundingClientRect on an orphan element raises
      // an "Unspecified Error". All other browsers return zeros.
      return new goog.math.Rect(0, 0, 0, 0);
    }

    var rect = new goog.math.Rect(nativeRect.left, nativeRect.top,
      nativeRect.right - nativeRect.left, nativeRect.bottom - nativeRect.top);

    // In IE, the element can additionally be offset by a border around the
    // documentElement or body element that we have to subtract.
    if (goog.userAgent.IE && elem.ownerDocument.body) {
      var doc = goog.dom.getOwnerDocument(elem);
      rect.left -= doc.documentElement.clientLeft + doc.body.clientLeft;
      rect.top -= doc.documentElement.clientTop + doc.body.clientTop;
    }

    return rect;
  }
};


/**
 * If given a <map> or <area> element, finds the corresponding image and client
 * rectangle of the element; otherwise returns null. The return value is an
 * object with 'image' and 'rect' properties. When no image uses the given
 * element, the returned rectangle is present but has zero size.
 *
 * @param {!Element} elem Element to test.
 * @return {?{image: Element, rect: !goog.math.Rect}} Image and rectangle.
 * @private
 */
bot.dom.maybeFindImageMap_ = function (elem) {
  // If not a <map> or <area>, return null indicating so.
  var isMap = bot.dom.isElement(elem, goog.dom.TagName.MAP);
  if (!isMap && !bot.dom.isElement(elem, goog.dom.TagName.AREA)) {
    return null;
  }

  // Get the <map> associated with this element, or null if none.
  var map = isMap ? elem :
    (bot.dom.isElement(elem.parentNode, goog.dom.TagName.MAP) ?
      elem.parentNode : null);

  var image = null, rect = null;
  if (map && map.name) {
    var mapDoc = goog.dom.getOwnerDocument(map);

    // TODO: Restrict to applet, img, input:image, and object nodes.
    var locator = '*[usemap="#' + map.name + '"]';

    // TODO: Break dependency of bot.locators on bot.dom,
    // so bot.locators.findElement can be called here instead.
    image = bot.locators.css.single(locator, mapDoc);

    if (image) {
      rect = bot.dom.getClientRect(image);
      if (!isMap && elem.shape.toLowerCase() != 'default') {
        // Shift and crop the relative area rectangle to the map.
        var relRect = bot.dom.getAreaRelativeRect_(elem);
        var relX = Math.min(Math.max(relRect.left, 0), rect.width);
        var relY = Math.min(Math.max(relRect.top, 0), rect.height);
        var w = Math.min(relRect.width, rect.width - relX);
        var h = Math.min(relRect.height, rect.height - relY);
        rect = new goog.math.Rect(relX + rect.left, relY + rect.top, w, h);
      }
    }
  }

  return { image: image, rect: rect || new goog.math.Rect(0, 0, 0, 0) };
};


/**
 * Returns the bounding box around an <area> element relative to its enclosing
 * <map>. Does not apply to <area> elements with shape=='default'.
 *
 * @param {!Element} area Area element.
 * @return {!goog.math.Rect} Bounding box of the area element.
 * @private
 */
bot.dom.getAreaRelativeRect_ = function (area) {
  var shape = area.shape.toLowerCase();
  var coords = area.coords.split(',');
  if (shape == 'rect' && coords.length == 4) {
    var x = coords[0], y = coords[1];
    return new goog.math.Rect(x, y, coords[2] - x, coords[3] - y);
  } else if (shape == 'circle' && coords.length == 3) {
    var centerX = coords[0], centerY = coords[1], radius = coords[2];
    return new goog.math.Rect(centerX - radius, centerY - radius,
      2 * radius, 2 * radius);
  } else if (shape == 'poly' && coords.length > 2) {
    var minX = coords[0], minY = coords[1], maxX = minX, maxY = minY;
    for (var i = 2; i + 1 < coords.length; i += 2) {
      minX = Math.min(minX, coords[i]);
      maxX = Math.max(maxX, coords[i]);
      minY = Math.min(minY, coords[i + 1]);
      maxY = Math.max(maxY, coords[i + 1]);
    }
    return new goog.math.Rect(minX, minY, maxX - minX, maxY - minY);
  }
  return new goog.math.Rect(0, 0, 0, 0);
};


/**
 * Gets the element's client rectangle as a box, optionally clipped to the
 * given coordinate or rectangle relative to the client's position. A coordinate
 * is treated as a 1x1 rectangle whose top-left corner is the coordinate.
 *
 * @param {!Element} elem The element.
 * @param {!(goog.math.Coordinate|goog.math.Rect)=} opt_region
 *     Coordinate or rectangle relative to the top-left corner of the element.
 * @return {!goog.math.Box} The client region box.
 */
bot.dom.getClientRegion = function (elem, opt_region) {
  var region = bot.dom.getClientRect(elem).toBox();

  if (opt_region) {
    var rect = opt_region instanceof goog.math.Rect ? opt_region :
      new goog.math.Rect(opt_region.x, opt_region.y, 1, 1);
    region.left = goog.math.clamp(
      region.left + rect.left, region.left, region.right);
    region.top = goog.math.clamp(
      region.top + rect.top, region.top, region.bottom);
    region.right = goog.math.clamp(
      region.left + rect.width, region.left, region.right);
    region.bottom = goog.math.clamp(
      region.top + rect.height, region.top, region.bottom);
  }

  return region;
};


/**
 * Trims leading and trailing whitespace from strings, leaving non-breaking
 * space characters in place.
 *
 * @param {string} str The string to trim.
 * @return {string} str without any leading or trailing whitespace characters
 *     except non-breaking spaces.
 * @private
 */
bot.dom.trimExcludingNonBreakingSpaceCharacters_ = function (str) {
  return str.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g, '');
};


/**
 * Helper function for getVisibleText[InDisplayedDom].
 * @param {!Array.<string>} lines Accumulated visible lines of text.
 * @return {string} cleaned up concatenated lines
 * @private
 */
bot.dom.concatenateCleanedLines_ = function (lines) {
  lines = goog.array.map(
    lines,
    bot.dom.trimExcludingNonBreakingSpaceCharacters_);
  var joined = lines.join('\n');
  var trimmed = bot.dom.trimExcludingNonBreakingSpaceCharacters_(joined);

  // Replace non-breakable spaces with regular ones.
  return trimmed.replace(/\xa0/g, ' ');
};


/**
 * @param {!Element} elem The element to consider.
 * @return {string} visible text.
 */
bot.dom.getVisibleText = function (elem) {
  var lines = [];

  if (bot.dom.IS_SHADOW_DOM_ENABLED) {
    bot.dom.appendVisibleTextLinesFromElementInComposedDom_(elem, lines);
  } else {
    bot.dom.appendVisibleTextLinesFromElement_(elem, lines);
  }
  return bot.dom.concatenateCleanedLines_(lines);
};


/**
 * Helper function used by bot.dom.appendVisibleTextLinesFromElement_ and
 * bot.dom.appendVisibleTextLinesFromElementInComposedDom_
 * @param {!Element} elem Element.
 * @param {!Array.<string>} lines Accumulated visible lines of text.
 * @param {function(!Element):boolean} isShownFn function to call to
 *     tell if an element is shown
 * @param {function(!Node, !Array.<string>, boolean, ?string, ?string):void}
 *     childNodeFn function to call to append lines from any child nodes
 * @private
 */
bot.dom.appendVisibleTextLinesFromElementCommon_ = function (
  elem, lines, isShownFn, childNodeFn) {
  function currLine() {
    return /** @type {string|undefined} */ (goog.array.peek(lines)) || '';
  }

  // TODO: Add case here for textual form elements.
  if (bot.dom.isElement(elem, goog.dom.TagName.BR)) {
    lines.push('');
  } else {
    // TODO: properly handle display:run-in
    var isTD = bot.dom.isElement(elem, goog.dom.TagName.TD);
    var display = bot.dom.getEffectiveStyle(elem, 'display');
    // On some browsers, table cells incorrectly show up with block styles.
    var isBlock = !isTD &&
      !goog.array.contains(bot.dom.INLINE_DISPLAY_BOXES_, display);

    // Add a newline before block elems when there is text on the current line,
    // except when the previous sibling has a display: run-in.
    // Also, do not run-in the previous sibling if this element is floated.

    var previousElementSibling = goog.dom.getPreviousElementSibling(elem);
    var prevDisplay = (previousElementSibling) ?
      bot.dom.getEffectiveStyle(previousElementSibling, 'display') : '';
    // TODO: getEffectiveStyle should mask this for us
    var thisFloat = bot.dom.getEffectiveStyle(elem, 'float') ||
      bot.dom.getEffectiveStyle(elem, 'cssFloat') ||
      bot.dom.getEffectiveStyle(elem, 'styleFloat');
    var runIntoThis = prevDisplay == 'run-in' && thisFloat == 'none';
    if (isBlock && !runIntoThis &&
      !goog.string.isEmptyOrWhitespace(currLine())) {
      lines.push('');
    }

    // This element may be considered unshown, but have a child that is
    // explicitly shown (e.g. this element has "visibility:hidden").
    // Nevertheless, any text nodes that are direct descendants of this
    // element will not contribute to the visible text.
    var shown = isShownFn(elem);

    // All text nodes that are children of this element need to know the
    // effective "white-space" and "text-transform" styles to properly
    // compute their contribution to visible text. Compute these values once.
    var whitespace = null, textTransform = null;
    if (shown) {
      whitespace = bot.dom.getEffectiveStyle(elem, 'white-space');
      textTransform = bot.dom.getEffectiveStyle(elem, 'text-transform');
    }

    goog.array.forEach(elem.childNodes, function (node) {
      childNodeFn(node, lines, shown, whitespace, textTransform);
    });

    var line = currLine();

    // Here we differ from standard innerText implementations (if there were
    // such a thing). Usually, table cells are separated by a tab, but we
    // normalize tabs into single spaces.
    if ((isTD || display == 'table-cell') && line &&
      !goog.string.endsWith(line, ' ')) {
      lines[lines.length - 1] += ' ';
    }

    // Add a newline after block elems when there is text on the current line,
    // and the current element isn't marked as run-in.
    if (isBlock && display != 'run-in' &&
      !goog.string.isEmptyOrWhitespace(line)) {
      lines.push('');
    }
  }
};


/**
 * @param {!Element} elem Element.
 * @param {!Array.<string>} lines Accumulated visible lines of text.
 * @private
 */
bot.dom.appendVisibleTextLinesFromElement_ = function (elem, lines) {
  bot.dom.appendVisibleTextLinesFromElementCommon_(
    elem, lines, bot.dom.isShown,
    function (node, lines, shown, whitespace, textTransform) {
      if (node.nodeType == goog.dom.NodeType.TEXT && shown) {
        var textNode = /** @type {!Text} */ (node);
        bot.dom.appendVisibleTextLinesFromTextNode_(textNode, lines,
          whitespace, textTransform);
      } else if (bot.dom.isElement(node)) {
        var castElem = /** @type {!Element} */ (node);
        bot.dom.appendVisibleTextLinesFromElement_(castElem, lines);
      }
    });
};


/**
 * Elements with one of these effective "display" styles are treated as inline
 * display boxes and have their visible text appended to the current line.
 * @private {!Array.<string>}
 * @const
 */
bot.dom.INLINE_DISPLAY_BOXES_ = [
  'inline',
  'inline-block',
  'inline-table',
  'none',
  'table-cell',
  'table-column',
  'table-column-group'
];


/**
 * @param {!Text} textNode Text node.
 * @param {!Array.<string>} lines Accumulated visible lines of text.
 * @param {?string} whitespace Parent element's "white-space" style.
 * @param {?string} textTransform Parent element's "text-transform" style.
 * @private
 */
bot.dom.appendVisibleTextLinesFromTextNode_ = function (textNode, lines,
  whitespace, textTransform) {

  // First, remove zero-width characters. Do this before regularizing spaces as
  // the zero-width space is both zero-width and a space, but we do not want to
  // make it visible by converting it to a regular space.
  // The replaced characters are:
  //   U+200B: Zero-width space
  //   U+200E: Left-to-right mark
  //   U+200F: Right-to-left mark
  var text = textNode.nodeValue.replace(/[\u200b\u200e\u200f]/g, '');

  // Canonicalize the new lines, and then collapse new lines
  // for the whitespace styles that collapse. See:
  // https://developer.mozilla.org/en/CSS/white-space
  text = goog.string.canonicalizeNewlines(text);
  if (whitespace == 'normal' || whitespace == 'nowrap') {
    text = text.replace(/\n/g, ' ');
  }

  // For pre and pre-wrap whitespace styles, convert all breaking spaces to be
  // non-breaking, otherwise, collapse all breaking spaces. Breaking spaces are
  // converted to regular spaces by getVisibleText().
  if (whitespace == 'pre' || whitespace == 'pre-wrap') {
    text = text.replace(/[ \f\t\v\u2028\u2029]/g, '\xa0');
  } else {
    text = text.replace(/[\ \f\t\v\u2028\u2029]+/g, ' ');
  }

  if (textTransform == 'capitalize') {
    // 1) don't treat '_' as a separator (protects snake_case)
    var re = /(^|[^'_0-9A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24B6-\u24E9\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF])([A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24B6-\u24E9])/g;
    text = text.replace(re, function () {
      return arguments[1] + arguments[2].toUpperCase();
    });

    // 2) capitalize after opening "_" or "*"
    // Preceded by start or a non-word (so it won't fire for snake_case)
    re = /(^|[^'_0-9A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24B6-\u24E9])([_*])([A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24D0-\u24E9])/g;
    text = text.replace(re, function () {
      return arguments[1] + arguments[2] + arguments[3].toUpperCase();
    });
  } else if (textTransform == 'uppercase') {
    text = text.toUpperCase();
  } else if (textTransform == 'lowercase') {
    text = text.toLowerCase();
  }

  var currLine = lines.pop() || '';
  if (goog.string.endsWith(currLine, ' ') &&
    goog.string.startsWith(text, ' ')) {
    text = text.substr(1);
  }
  lines.push(currLine + text);
};


/**
 * Gets the opacity of a node (x-browser).
 * This gets the inline style opacity of the node and takes into account the
 * cascaded or the computed style for this node.
 *
 * @param {!Element} elem Element whose opacity has to be found.
 * @return {number} Opacity between 0 and 1.
 */
bot.dom.getOpacity = function (elem) {
  // TODO: Does this need to deal with rgba colors?
  if (!bot.userAgent.IE_DOC_PRE9) {
    return bot.dom.getOpacityNonIE_(elem);
  } else {
    if (bot.dom.getEffectiveStyle(elem, 'position') == 'relative') {
      // Filter does not apply to non positioned elements.
      return 1;
    }

    var opacityStyle = bot.dom.getEffectiveStyle(elem, 'filter');
    var groups = opacityStyle.match(/^alpha\(opacity=(\d*)\)/) ||
      opacityStyle.match(
        /^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/);

    if (groups) {
      return Number(groups[1]) / 100;
    } else {
      return 1; // Opaque.
    }
  }
};


/**
 * Implementation of getOpacity for browsers that do support
 * the "opacity" style.
 *
 * @param {!Element} elem Element whose opacity has to be found.
 * @return {number} Opacity between 0 and 1.
 * @private
 */
bot.dom.getOpacityNonIE_ = function (elem) {
  // By default the element is opaque.
  var elemOpacity = 1;

  var opacityStyle = bot.dom.getEffectiveStyle(elem, 'opacity');
  if (opacityStyle) {
    elemOpacity = Number(opacityStyle);
  }

  // Let's apply the parent opacity to the element.
  var parentElement = bot.dom.getParentElement(elem);
  if (parentElement) {
    elemOpacity = elemOpacity * bot.dom.getOpacityNonIE_(parentElement);
  }
  return elemOpacity;
};


/**
 * Returns the display parent element of the given node, or null. This method
 * differs from bot.dom.getParentElement in the presence of ShadowDOM and
 * &lt;shadow&gt; or &lt;content&gt; tags. For example if
 * <ul>
 * <li>div A contains div B
 * <li>div B has a css class .C
 * <li>div A contains a Shadow DOM with a div D
 * <li>div D contains a contents tag selecting all items of class .C
 * </ul>
 * then calling bot.dom.getParentElement on B will return A, but calling
 * getDisplayParentElement on B will return D.
 *
 * @param {!Node} node The node whose parent is desired.
 * @return {Node} The parent node, if available, null otherwise.
 */
bot.dom.getParentNodeInComposedDom = function (node) {
  var /**@type {Node}*/ parent = node.parentNode;

  // Shadow DOM v1
  if (parent && parent.shadowRoot && node.assignedSlot !== undefined) {
    // Can be null on purpose, meaning it has no parent as
    // it hasn't yet been slotted
    return node.assignedSlot ? node.assignedSlot.parentNode : null;
  }

  // Shadow DOM V0 (deprecated)
  if (node.getDestinationInsertionPoints) {
    var destinations = node.getDestinationInsertionPoints();
    if (destinations.length > 0) {
      return destinations[destinations.length - 1];
    }
  }

  return parent;
};


/**
 * @param {!Node} node Node.
 * @param {!Array.<string>} lines Accumulated visible lines of text.
 * @param {boolean} shown whether the node is visible
 * @param {?string} whitespace the node's 'white-space' effectiveStyle
 * @param {?string} textTransform the node's 'text-transform' effectiveStyle
 * @private
 * @suppress {missingProperties}
 */
bot.dom.appendVisibleTextLinesFromNodeInComposedDom_ = function (
  node, lines, shown, whitespace, textTransform) {

  if (node.nodeType == goog.dom.NodeType.TEXT && shown) {
    var textNode = /** @type {!Text} */ (node);
    bot.dom.appendVisibleTextLinesFromTextNode_(textNode, lines,
      whitespace, textTransform);
  } else if (bot.dom.isElement(node)) {
    var castElem = /** @type {!Element} */ (node);

    if (bot.dom.isElement(node, 'CONTENT') || bot.dom.isElement(node, 'SLOT')) {
      var parentNode = node;
      while (parentNode.parentNode) {
        parentNode = parentNode.parentNode;
      }
      if (parentNode instanceof ShadowRoot) {
        // If the element is <content> and we're inside a shadow DOM then just
        // append the contents of the nodes that have been distributed into it.
        var contentElem = /** @type {!Object} */ (node);
        var shadowChildren;
        if (bot.dom.isElement(node, 'CONTENT')) {
          shadowChildren = contentElem.getDistributedNodes();
        } else {
          shadowChildren = contentElem.assignedNodes();
        }
        const childrenToTraverse =
          shadowChildren.length > 0 ? shadowChildren : contentElem.childNodes;
        goog.array.forEach(childrenToTraverse, function (node) {
          bot.dom.appendVisibleTextLinesFromNodeInComposedDom_(
            node, lines, shown, whitespace, textTransform);
        });
      } else {
        // if we're not inside a shadow DOM, then we just treat <content>
        // as an unknown element and use anything inside the tag
        bot.dom.appendVisibleTextLinesFromElementInComposedDom_(
          castElem, lines);
      }
    } else if (bot.dom.isElement(node, 'SHADOW')) {
      // if the element is <shadow> then find the owning shadowRoot
      var parentNode = node;
      while (parentNode.parentNode) {
        parentNode = parentNode.parentNode;
      }
      if (parentNode instanceof ShadowRoot) {
        var thisShadowRoot = /** @type {!ShadowRoot} */ (parentNode);
        if (thisShadowRoot) {
          // then go through the owning shadowRoots older siblings and append
          // their contents
          var olderShadowRoot = thisShadowRoot.olderShadowRoot;
          while (olderShadowRoot) {
            goog.array.forEach(
              olderShadowRoot.childNodes, function (childNode) {
                bot.dom.appendVisibleTextLinesFromNodeInComposedDom_(
                  childNode, lines, shown, whitespace, textTransform);
              });
            olderShadowRoot = olderShadowRoot.olderShadowRoot;
          }
        }
      }
    } else {
      // otherwise append the contents of an element as per normal.
      bot.dom.appendVisibleTextLinesFromElementInComposedDom_(
        castElem, lines);
    }
  }
};


/**
 * Determines whether a given node has been distributed into a ShadowDOM
 * element somewhere.
 * @param {!Node} node The node to check
 * @return {boolean} True if the node has been distributed.
 */
bot.dom.isNodeDistributedIntoShadowDom = function (node) {
  var elemOrText = null;
  if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    elemOrText = /** @type {!Element} */ (node);
  } else if (node.nodeType == goog.dom.NodeType.TEXT) {
    elemOrText = /** @type {!Text} */ (node);
  }
  return elemOrText != null &&
    (elemOrText.assignedSlot != null ||
      (elemOrText.getDestinationInsertionPoints &&
        elemOrText.getDestinationInsertionPoints().length > 0)
    );
};


/**
 * @param {!Element} elem Element.
 * @param {!Array.<string>} lines Accumulated visible lines of text.
 * @private
 */
bot.dom.appendVisibleTextLinesFromElementInComposedDom_ = function (
  elem, lines) {
  if (elem.shadowRoot) {
    // Get the effective styles from the shadow host element for text nodes in shadow DOM
    var whitespace = bot.dom.getEffectiveStyle(elem, 'white-space');
    var textTransform = bot.dom.getEffectiveStyle(elem, 'text-transform');

    goog.array.forEach(elem.shadowRoot.childNodes, function (node) {
      bot.dom.appendVisibleTextLinesFromNodeInComposedDom_(
        node, lines, true, whitespace, textTransform);
    });
  }

  bot.dom.appendVisibleTextLinesFromElementCommon_(
    elem, lines, bot.dom.isShown,
    function (node, lines, shown, whitespace, textTransform) {
      // If the node has been distributed into a shadowDom element
      // to be displayed elsewhere, then we shouldn't append
      // its contents here).
      if (!bot.dom.isNodeDistributedIntoShadowDom(node)) {
        bot.dom.appendVisibleTextLinesFromNodeInComposedDom_(
          node, lines, shown, whitespace, textTransform);
      }
    });
};
