| Index: ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
 | 
| diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
 | 
| index 17b91df4af7ed32d2e72a4c742a5c0c1f8b25912..5979235e5c761c4d75adf71b9217044756a4cd6c 100644
 | 
| --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
 | 
| +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
 | 
| @@ -6,14 +6,14 @@
 | 
|   * @typedef {{
 | 
|   *   top: number,
 | 
|   *   left: number,
 | 
| - *   width: (number| undefined),
 | 
| - *   height: (number| undefined),
 | 
| - *   anchorAlignmentX: (number| undefined),
 | 
| - *   anchorAlignmentY: (number| undefined),
 | 
| - *   minX: (number| undefined),
 | 
| - *   minY: (number| undefined),
 | 
| - *   maxX: (number| undefined),
 | 
| - *   maxY: (number| undefined),
 | 
| + *   width: (number|undefined),
 | 
| + *   height: (number|undefined),
 | 
| + *   anchorAlignmentX: (number|undefined),
 | 
| + *   anchorAlignmentY: (number|undefined),
 | 
| + *   minX: (number|undefined),
 | 
| + *   minY: (number|undefined),
 | 
| + *   maxX: (number|undefined),
 | 
| + *   maxY: (number|undefined),
 | 
|   * }}
 | 
|   */
 | 
|  var ShowConfig;
 | 
| @@ -73,12 +73,12 @@ function getStartPointWithAnchor(
 | 
|    return startPoint;
 | 
|  }
 | 
|  
 | 
| -
 | 
|  /**
 | 
|   * @private
 | 
|   * @return {!ShowConfig}
 | 
|   */
 | 
|  function getDefaultShowConfig() {
 | 
| +  var doc = document.scrollingElement;
 | 
|    return {
 | 
|      top: 0,
 | 
|      left: 0,
 | 
| @@ -86,10 +86,10 @@ function getDefaultShowConfig() {
 | 
|      width: 0,
 | 
|      anchorAlignmentX: AnchorAlignment.AFTER_START,
 | 
|      anchorAlignmentY: AnchorAlignment.AFTER_START,
 | 
| -    minX: 0,
 | 
| -    minY: 0,
 | 
| -    maxX: window.innerWidth,
 | 
| -    maxY: window.innerHeight,
 | 
| +    minX: doc.scrollLeft,
 | 
| +    minY: doc.scrollTop,
 | 
| +    maxX: doc.scrollLeft + window.innerWidth,
 | 
| +    maxY: doc.scrollTop + window.innerHeight,
 | 
|    };
 | 
|  }
 | 
|  
 | 
| @@ -242,19 +242,49 @@ Polymer({
 | 
|    /**
 | 
|     * Shows the menu anchored to the given element.
 | 
|     * @param {!Element} anchorElement
 | 
| +   * @param {ShowConfig=} opt_config
 | 
|     */
 | 
| -  showAt: function(anchorElement) {
 | 
| +  showAt: function(anchorElement, opt_config) {
 | 
|      this.anchorElement_ = anchorElement;
 | 
| +    // Scroll the anchor element into view so that the bounding rect will be
 | 
| +    // accurate for where the menu should be shown.
 | 
|      this.anchorElement_.scrollIntoViewIfNeeded();
 | 
| +
 | 
| +    // Save the scroll position that ensures the anchor element is onscreen.
 | 
| +    var doc = document.scrollingElement;
 | 
| +    var scrollLeft = doc.scrollLeft;
 | 
| +    var scrollTop = doc.scrollTop;
 | 
| +
 | 
| +    // Reset position so that layout isn't affected by the previous position,
 | 
| +    // and so that the dialog is positioned at the top-start corner of the
 | 
| +    // document.
 | 
| +    this.resetStyle_();
 | 
| +
 | 
| +    // Show the dialog which will focus the top-start of the body. This makes
 | 
| +    // the client rect calculation relative to the top-start of the body.
 | 
| +    this.showModal();
 | 
| +
 | 
|      var rect = this.anchorElement_.getBoundingClientRect();
 | 
| -    this.showAtPosition({
 | 
| -      top: rect.top,
 | 
| -      left: rect.left,
 | 
| -      height: rect.height,
 | 
| -      width: rect.width,
 | 
| -      // Default to anchoring towards the left.
 | 
| -      anchorAlignmentX: AnchorAlignment.BEFORE_END,
 | 
| -    });
 | 
| +    this.positionDialog_(/** @type {ShowConfig} */ (Object.assign(
 | 
| +        {
 | 
| +          top: rect.top,
 | 
| +          left: rect.left,
 | 
| +          height: rect.height,
 | 
| +          width: rect.width,
 | 
| +          // Default to anchoring towards the left.
 | 
| +          anchorAlignmentX: AnchorAlignment.BEFORE_END,
 | 
| +          minX: scrollLeft,
 | 
| +          minY: scrollTop,
 | 
| +          maxX: scrollLeft + window.innerWidth,
 | 
| +          maxY: scrollTop + window.innerHeight,
 | 
| +        },
 | 
| +        opt_config)));
 | 
| +
 | 
| +    // Restore the scroll position.
 | 
| +    doc.scrollTop = scrollTop;
 | 
| +    doc.scrollLeft = scrollLeft;
 | 
| +
 | 
| +    this.addCloseListeners_();
 | 
|    },
 | 
|  
 | 
|    /**
 | 
| @@ -284,6 +314,24 @@ Polymer({
 | 
|     * @param {!ShowConfig} config
 | 
|     */
 | 
|    showAtPosition: function(config) {
 | 
| +    this.resetStyle_();
 | 
| +    this.showModal();
 | 
| +    this.positionDialog_(config);
 | 
| +    this.addCloseListeners_();
 | 
| +  },
 | 
| +
 | 
| +  /** @private */
 | 
| +  resetStyle_: function() {
 | 
| +    this.style.left = '';
 | 
| +    this.style.right = '';
 | 
| +    this.style.top = '0';
 | 
| +  },
 | 
| +
 | 
| +  /**
 | 
| +   * @param {!ShowConfig} config
 | 
| +   * @private
 | 
| +   */
 | 
| +  positionDialog_: function(config) {
 | 
|      var c = Object.assign(getDefaultShowConfig(), config);
 | 
|  
 | 
|      var top = c.top;
 | 
| @@ -291,20 +339,6 @@ Polymer({
 | 
|      var bottom = top + c.height;
 | 
|      var right = left + c.width;
 | 
|  
 | 
| -    this.boundClose_ = this.boundClose_ || function() {
 | 
| -      if (this.open)
 | 
| -        this.close();
 | 
| -    }.bind(this);
 | 
| -    window.addEventListener('resize', this.boundClose_);
 | 
| -    window.addEventListener('popstate', this.boundClose_);
 | 
| -
 | 
| -    // Reset position to prevent previous values from affecting layout.
 | 
| -    this.style.left = '';
 | 
| -    this.style.right = '';
 | 
| -    this.style.top = '';
 | 
| -
 | 
| -    this.showModal();
 | 
| -
 | 
|      // Flip the X anchor in RTL.
 | 
|      var rtl = getComputedStyle(this).direction == 'rtl';
 | 
|      if (rtl)
 | 
| @@ -314,7 +348,7 @@ Polymer({
 | 
|          left, right, this.offsetWidth, c.anchorAlignmentX, c.minX, c.maxX);
 | 
|  
 | 
|      if (rtl) {
 | 
| -      var menuRight = window.innerWidth - menuLeft - this.offsetWidth;
 | 
| +      var menuRight = document.body.scrollWidth - menuLeft - this.offsetWidth;
 | 
|        this.style.right = menuRight + 'px';
 | 
|      } else {
 | 
|        this.style.left = menuLeft + 'px';
 | 
| @@ -324,5 +358,17 @@ Polymer({
 | 
|          top, bottom, this.offsetHeight, c.anchorAlignmentY, c.minY, c.maxY);
 | 
|      this.style.top = menuTop + 'px';
 | 
|    },
 | 
| +
 | 
| +  /**
 | 
| +   * @private
 | 
| +   */
 | 
| +  addCloseListeners_: function() {
 | 
| +    this.boundClose_ = this.boundClose_ || function() {
 | 
| +      if (this.open)
 | 
| +        this.close();
 | 
| +    }.bind(this);
 | 
| +    window.addEventListener('resize', this.boundClose_);
 | 
| +    window.addEventListener('popstate', this.boundClose_);
 | 
| +  },
 | 
|  });
 | 
|  })();
 | 
| 
 |