From d191f3c24b0c7384b9f59b2c39db6f35c3549e97 Mon Sep 17 00:00:00 2001
From: "lazyboy@chromium.org"
 <lazyboy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Thu, 5 Sep 2013 13:16:26 +0000
Subject: Reland attempt 2: Improve <webview> autosize:

a. Expand/shrink <webview> element when 'sizechange' event fires, to
match with the new view size (in shim).
b. For SW mode, fix a bug where damage buffer would remain smaller than
the view size and would result in crash. Added test for this case.

BUG=173238, 282116
Test=WebViewTest.AutoSize.*, <webview>.autosize=true now should autosize
webview container within the constraints
(minwidth/maxwidth/minheight/maxheight).

Review URL: https://chromiumcodereview.appspot.com/23691039

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221402 0039d316-1c4b-4281-b951-d872f2087c98
---
 chrome/browser/apps/web_view_browsertest.cc        | 29 ++++++-
 chrome/renderer/resources/extensions/web_view.js   | 75 ++++++++++++++++-
 .../platform_apps/web_view/autosize/main.html      | 11 +++
 .../platform_apps/web_view/autosize/main.js        | 63 ++++++++++++++
 .../platform_apps/web_view/autosize/manifest.json  | 13 +++
 .../platform_apps/web_view/autosize/test.js        |  7 ++
 .../extensions/platform_apps/web_view/shim/main.js | 40 ++++-----
 .../browser/browser_plugin/browser_plugin_guest.cc |  1 +
 content/renderer/browser_plugin/browser_plugin.cc  | 98 ++++++++++++++--------
 content/renderer/browser_plugin/browser_plugin.h   | 16 ++--
 10 files changed, 282 insertions(+), 71 deletions(-)
 create mode 100644 chrome/test/data/extensions/platform_apps/web_view/autosize/main.html
 create mode 100644 chrome/test/data/extensions/platform_apps/web_view/autosize/main.js
 create mode 100644 chrome/test/data/extensions/platform_apps/web_view/autosize/manifest.json
 create mode 100644 chrome/test/data/extensions/platform_apps/web_view/autosize/test.js

diff --git a/chrome/browser/apps/web_view_browsertest.cc b/chrome/browser/apps/web_view_browsertest.cc
index c28bdf8..4e6a565 100644
--- a/chrome/browser/apps/web_view_browsertest.cc
+++ b/chrome/browser/apps/web_view_browsertest.cc
@@ -20,6 +20,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/fake_speech_recognition_manager.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -258,6 +259,17 @@ class WebViewTest : public extensions::PlatformAppBrowserTest {
     }
   }
 
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    const testing::TestInfo* const test_info =
+        testing::UnitTest::GetInstance()->current_test_info();
+
+    // Force SW rendering to check autosize bug.
+    if (!strncmp(test_info->name(), "AutoSizeSW", strlen("AutosizeSW")))
+      command_line->AppendSwitch(switches::kDisableForceCompositingMode);
+
+    extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line);
+  }
+
   // This method is responsible for initializing a packaged app, which contains
   // multiple webview tags. The tags have different partition identifiers and
   // their WebContent objects are returned as output. The method also verifies
@@ -567,6 +579,20 @@ IN_PROC_BROWSER_TEST_F(WebViewTest,
       << message_;
 }
 
+IN_PROC_BROWSER_TEST_F(WebViewTest, AutoSize) {
+  ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/autosize"))
+      << message_;
+}
+
+#if !defined(OS_CHROMEOS)
+// This test ensures <webview> doesn't crash in SW rendering when autosize is
+// turned on.
+IN_PROC_BROWSER_TEST_F(WebViewTest, AutoSizeSW) {
+  ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/autosize"))
+      << message_;
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAutosizeAfterNavigation) {
   TestHelper("testAutosizeAfterNavigation",
              "DoneShimTest.PASSED",
@@ -587,9 +613,8 @@ IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAutosizeRemoveAttributes) {
              "web_view/shim");
 }
 
-// This test is flaky. crbug.com/282116
 IN_PROC_BROWSER_TEST_F(WebViewTest,
-                       DISABLED_Shim_TestAutosizeWithPartialAttributes) {
+                       Shim_TestAutosizeWithPartialAttributes) {
   TestHelper("testAutosizeWithPartialAttributes",
              "DoneShimTest.PASSED",
              "DoneShimTest.FAILED",
diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js
index a3760d3..7954261 100644
--- a/chrome/renderer/resources/extensions/web_view.js
+++ b/chrome/renderer/resources/extensions/web_view.js
@@ -24,9 +24,21 @@ var WebView = require('binding').Binding.create('webview').generate();
 // API can access it and not external developers.
 var secret = {};
 
+var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight';
+var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth';
+var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight';
+var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth';
+
 /** @type {Array.<string>} */
-var WEB_VIEW_ATTRIBUTES = ['name', 'partition', 'autosize', 'minheight',
-    'minwidth', 'maxheight', 'maxwidth'];
+var WEB_VIEW_ATTRIBUTES = [
+    'name',
+    'partition',
+    'autosize',
+    WEB_VIEW_ATTRIBUTE_MINHEIGHT,
+    WEB_VIEW_ATTRIBUTE_MINWIDTH,
+    WEB_VIEW_ATTRIBUTE_MAXHEIGHT,
+    WEB_VIEW_ATTRIBUTE_MAXWIDTH
+];
 
 var webViewInstanceIdCounter = 0;
 
@@ -113,6 +125,9 @@ var WEB_VIEW_EVENTS = {
   },
   'sizechanged': {
     evt: CreateEvent('webview.onSizeChanged'),
+    customHandler: function(webViewInternal, event, webViewEvent) {
+      webViewInternal.handleSizeChangedEvent_(event, webViewEvent);
+    },
     fields: ['oldHeight', 'oldWidth', 'newHeight', 'newWidth']
   },
   'unresponsive': {
@@ -475,6 +490,62 @@ WebViewInternal.prototype.getEvents_ = function() {
   return WEB_VIEW_EVENTS;
 };
 
+WebViewInternal.prototype.handleSizeChangedEvent_ =
+    function(event, webViewEvent) {
+  var node = this.webviewNode_;
+
+  var width = node.offsetWidth;
+  var height = node.offsetHeight;
+
+  // Check the current bounds to make sure we do not resize <webview>
+  // outside of current constraints.
+  var maxWidth;
+  if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXWIDTH) &&
+      node[WEB_VIEW_ATTRIBUTE_MAXWIDTH]) {
+    maxWidth = node[WEB_VIEW_ATTRIBUTE_MAXWIDTH];
+  } else {
+    maxWidth = width;
+  }
+
+  var minWidth;
+  if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINWIDTH) &&
+      node[WEB_VIEW_ATTRIBUTE_MINWIDTH]) {
+    minWidth = node[WEB_VIEW_ATTRIBUTE_MINWIDTH];
+  } else {
+    minWidth = width;
+  }
+  if (minWidth > maxWidth) {
+    minWidth = maxWidth;
+  }
+
+  var maxHeight;
+  if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXHEIGHT) &&
+      node[WEB_VIEW_ATTRIBUTE_MAXHEIGHT]) {
+    maxHeight = node[WEB_VIEW_ATTRIBUTE_MAXHEIGHT];
+  } else {
+    maxHeight = height;
+  }
+  var minHeight;
+  if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINHEIGHT) &&
+      node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]) {
+    minHeight = node[WEB_VIEW_ATTRIBUTE_MINHEIGHT];
+  } else {
+    minHeight = height;
+  }
+  if (minHeight > maxHeight) {
+    minHeight = maxHeight;
+  }
+
+  if (webViewEvent.newWidth >= minWidth &&
+      webViewEvent.newWidth <= maxWidth &&
+      webViewEvent.newHeight >= minHeight &&
+      webViewEvent.newHeight <= maxHeight) {
+    node.style.width = webViewEvent.newWidth + 'px';
+    node.style.height = webViewEvent.newHeight + 'px';
+  }
+  node.dispatchEvent(webViewEvent);
+};
+
 /**
  * @private
  */
diff --git a/chrome/test/data/extensions/platform_apps/web_view/autosize/main.html b/chrome/test/data/extensions/platform_apps/web_view/autosize/main.html
new file mode 100644
index 0000000..eb81450
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/autosize/main.html
@@ -0,0 +1,11 @@
+<!--
+ * Copyright 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.
+-->
+<html>
+<body>
+  <webview style="width: 300px; height: 200px"></webview>
+  <script src="main.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/autosize/main.js b/chrome/test/data/extensions/platform_apps/web_view/autosize/main.js
new file mode 100644
index 0000000..017d741
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/autosize/main.js
@@ -0,0 +1,63 @@
+// Copyright 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.
+
+function testAutoSize() {
+  var webview = document.querySelector('webview');
+
+  var minw = 1600;
+  var maxw = 3000;
+  var minh = 1600;
+  var maxh = 3000;
+
+  webview.addEventListener('loadstop', function(e) {
+    window.console.log('guest.loadstop');
+    // Note that we set the autosize attribute first to check incorrect
+    // damage buffer allocation.
+    //
+    // Consider a case where:
+    // Initially, <webview>.width = 300 (default width).
+    // Then we set
+    // <webview>.autosize = true
+    // And then we set
+    // <webview>.minwidth = 200
+    // and
+    // <webview>.maxwidth = 800
+    // If the autosize logic decided to set the width to 400 (something > 300),
+    // then we won't have enough memory in damage buffer to render.
+    // When tried manually, this would cause garbage to be rendered (around the
+    // bottom portion of plugin). In test we set the value to high so increase
+    // the chance of invalid memory access.
+    webview.autosize = true;
+
+    // Ask for a larger size so we can expose memory access bug.
+    webview.maxwidth = maxw;
+    webview.maxheight = maxh;
+    webview.minwidth = minw;
+    webview.minheight = minh;
+  });
+
+  webview.addEventListener('sizechanged', function(e) {
+    window.console.log('sizechagned: dimension: ' + e.newWidth + ' X ' +
+                       e.newHeight);
+    chrome.test.assertTrue(e.newWidth >= minw);
+    chrome.test.assertTrue(e.newWidth <= maxw);
+    chrome.test.assertTrue(e.newHeight >= minh);
+    chrome.test.assertTrue(e.newHeight <= maxh);
+
+    chrome.test.succeed();
+  });
+
+  var longString = 'a b c d e f g h i j k l m o p q r s t u v w x y z';
+  for (var i = 0; i < 4; ++i) {
+    longString += longString;
+  }
+  webview.setAttribute('src',
+      'data:text/html,<body bgcolor="red">' +
+      '<div style="width: 400px; height: 200px;">' + longString + '</div>' +
+      longString + '</body>');
+}
+
+onload = function() {
+  chrome.test.runTests([testAutoSize]);
+};
diff --git a/chrome/test/data/extensions/platform_apps/web_view/autosize/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/autosize/manifest.json
new file mode 100644
index 0000000..8182fb2
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/autosize/manifest.json
@@ -0,0 +1,13 @@
+{
+  "name": "Platform App Test: <webview>",
+  "description": "Checks autosize on <webview>",
+  "version": "1",
+  "permissions": [
+    "webview"
+  ],
+  "app": {
+    "background": {
+      "scripts": ["test.js"]
+    }
+  }
+}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/autosize/test.js b/chrome/test/data/extensions/platform_apps/web_view/autosize/test.js
new file mode 100644
index 0000000..2f9f855
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/autosize/test.js
@@ -0,0 +1,7 @@
+// Copyright 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.
+
+chrome.app.runtime.onLaunched.addListener(function() {
+  chrome.app.window.create('main.html', {}, function () {});
+});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
index f3690fe9..4156ce8 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
@@ -170,36 +170,30 @@ function testAutosizeWithPartialAttributes() {
 
   var step = 1;
   var sizeChangeHandler = function(e) {
+    window.console.log('sizeChangeHandler, new: ' +
+                       e.newWidth + ' X ' + e.newHeight);
     switch (step) {
       case 1:
         // Expect 300x200.
         embedder.test.assertEq(300, e.newWidth);
         embedder.test.assertEq(200, e.newHeight);
 
-        // Remove an autosize attribute and verify that it causes relayout.
-        webview.minwidth = null;
+        // Change the min size to cause a relayout.
+        webview.minwidth = 500;
         break;
       case 2:
-        // Expect 640x?
-        embedder.test.assertEq(640, e.newWidth);
+        embedder.test.assertTrue(e.newWidth >= webview.minwidth);
+        embedder.test.assertTrue(e.newWidth <= webview.maxwidth);
 
         // Tests when minwidth > maxwidth, minwidth = maxwidth.
-        webview.maxheight = null;
+        // i.e. minwidth is essentially 700.
         webview.minwidth = 800;
-        webview.minheight = 800;
         break;
       case 3:
-        // Expect 700X480
+        // Expect 700X?
         embedder.test.assertEq(700, e.newWidth);
-        embedder.test.assertEq(480, e.newHeight);
-
-        // Remove maxwidth and make sure the size returns to plugin size.
-        webview.removeAttribute('maxwidth');
-        break;
-      case 4:
-        // Expect original size, 640x480.
-        embedder.test.assertEq(640, e.newWidth);
-        embedder.test.assertEq(480, e.newHeight);
+        embedder.test.assertTrue(e.newHeight >= 200);
+        embedder.test.assertTrue(e.newHeight <= 600);
 
         embedder.test.succeed();
         break;
@@ -244,18 +238,16 @@ function testAutosizeRemoveAttributes() {
         webview.removeAttribute('maxwidth');
         webview.removeAttribute('minheight');
         webview.removeAttribute('maxheight');
+        webview.removeAttribute('autosize');
+
+        // We'd get one more sizechanged event after we turn off
+        // autosize.
+        webview.style.width = '500px';
+        webview.style.height = '500px';
         break;
       case 2:
-        // Expect plugin to return to its original size.
-        embedder.test.assertEq(640, e.newWidth);
-        embedder.test.assertEq(480, e.newHeight);
-
         embedder.test.succeed();
         break;
-      default:
-        window.console.log('Unexpected sizechanged event, step = ' + step);
-        embedder.test.fail();
-        break;
     }
 
     ++step;
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index fedd64d..9408e76 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -1399,6 +1399,7 @@ void BrowserPluginGuest::OnSetSize(
   if (auto_size_enabled_ && (!old_auto_size_enabled ||
                              (old_max_size != max_auto_size_) ||
                              (old_min_size != min_auto_size_))) {
+    RecordAction(UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
     GetWebContents()->GetRenderViewHost()->EnableAutoResize(
         min_auto_size_, max_auto_size_);
     // TODO(fsamuel): If we're changing autosize parameters, then we force
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index 0a14a4e..c80b8c7 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -76,11 +76,11 @@ BrowserPlugin::BrowserPlugin(
       render_view_routing_id_(render_view->GetRoutingID()),
       container_(NULL),
       damage_buffer_sequence_id_(0),
-      resize_ack_received_(true),
+      paint_ack_received_(true),
       last_device_scale_factor_(1.0f),
       sad_guest_(NULL),
       guest_crashed_(false),
-      auto_size_ack_pending_(false),
+      is_auto_size_state_dirty_(false),
       persist_storage_(false),
       valid_partition_id_(true),
       content_window_routing_id_(MSG_ROUTING_NONE),
@@ -295,35 +295,45 @@ bool BrowserPlugin::ParseSrcAttribute(std::string* error_message) {
 }
 
 void BrowserPlugin::ParseAutoSizeAttribute() {
-  auto_size_ack_pending_ = true;
   last_view_size_ = plugin_rect_.size();
+  is_auto_size_state_dirty_ = true;
   UpdateGuestAutoSizeState(GetAutoSizeAttribute());
 }
 
 void BrowserPlugin::PopulateAutoSizeParameters(
-    BrowserPluginHostMsg_AutoSize_Params* params, bool current_auto_size) {
-  params->enable = current_auto_size;
+    BrowserPluginHostMsg_AutoSize_Params* params, bool auto_size_enabled) {
+  params->enable = auto_size_enabled;
   // No need to populate the params if autosize is off.
-  if (current_auto_size) {
+  if (auto_size_enabled) {
     params->max_size = gfx::Size(GetAdjustedMaxWidth(), GetAdjustedMaxHeight());
     params->min_size = gfx::Size(GetAdjustedMinWidth(), GetAdjustedMinHeight());
+
+    if (max_auto_size_ != params->max_size)
+      is_auto_size_state_dirty_ = true;
+
+    max_auto_size_ = params->max_size;
+  } else {
+    max_auto_size_ = gfx::Size();
   }
 }
 
-void BrowserPlugin::UpdateGuestAutoSizeState(bool current_auto_size) {
+void BrowserPlugin::UpdateGuestAutoSizeState(bool auto_size_enabled) {
   // If we haven't yet heard back from the guest about the last resize request,
   // then we don't issue another request until we do in
   // BrowserPlugin::UpdateRect.
-  if (!HasGuestInstanceID() || !resize_ack_received_)
+  if (!HasGuestInstanceID() || !paint_ack_received_)
     return;
+
   BrowserPluginHostMsg_AutoSize_Params auto_size_params;
   BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params;
-  if (current_auto_size) {
-    GetDamageBufferWithSizeParams(&auto_size_params, &resize_guest_params);
+  if (auto_size_enabled) {
+    GetDamageBufferWithSizeParams(&auto_size_params,
+                                  &resize_guest_params,
+                                  true);
   } else {
-    GetDamageBufferWithSizeParams(NULL, &resize_guest_params);
+    GetDamageBufferWithSizeParams(NULL, &resize_guest_params, true);
   }
-  resize_ack_received_ = false;
+  paint_ack_received_ = false;
   browser_plugin_manager()->Send(
       new BrowserPluginHostMsg_SetAutoSize(render_view_routing_id_,
                                            guest_instance_id_,
@@ -365,7 +375,8 @@ void BrowserPlugin::Attach(scoped_ptr<base::DictionaryValue> extra_params) {
   attach_params.persist_storage = persist_storage_;
   attach_params.src = GetSrcAttribute();
   GetDamageBufferWithSizeParams(&attach_params.auto_size_params,
-                                &attach_params.resize_guest_params);
+                                &attach_params.resize_guest_params,
+                                false);
 
   browser_plugin_manager()->Send(
       new BrowserPluginHostMsg_Attach(render_view_routing_id_,
@@ -498,19 +509,20 @@ void BrowserPlugin::OnUpdateRect(
 
   bool auto_size = GetAutoSizeAttribute();
   // We receive a resize ACK in regular mode, but not in autosize.
-  // In SW, |resize_ack_received_| is reset in SwapDamageBuffers().
+  // In SW, |paint_ack_received_| is reset in SwapDamageBuffers().
   // In HW mode, we need to do it here so we can continue sending
   // resize messages when needed.
   if (params.is_resize_ack ||
-      (!params.needs_ack && (auto_size || auto_size_ack_pending_))) {
-    resize_ack_received_ = true;
+      (!params.needs_ack && (auto_size || is_auto_size_state_dirty_))) {
+    paint_ack_received_ = true;
   }
 
-  auto_size_ack_pending_ = false;
+  bool was_auto_size_state_dirty = auto_size && is_auto_size_state_dirty_;
+  is_auto_size_state_dirty_ = false;
 
   if ((!auto_size && (width() != params.view_size.width() ||
                       height() != params.view_size.height())) ||
-      (auto_size && (!InAutoSizeBounds(params.view_size))) ||
+      (auto_size && was_auto_size_state_dirty) ||
       GetDeviceScaleFactor() != params.scale_factor) {
     // We are HW accelerated, render widget does not expect an ack,
     // but we still need to update the size.
@@ -519,7 +531,7 @@ void BrowserPlugin::OnUpdateRect(
       return;
     }
 
-    if (!resize_ack_received_) {
+    if (!paint_ack_received_) {
       // The guest has not yet responded to the last resize request, and
       // so we don't want to do anything at this point other than ACK the guest.
       if (auto_size)
@@ -530,9 +542,12 @@ void BrowserPlugin::OnUpdateRect(
       // container size.
       if (auto_size) {
         GetDamageBufferWithSizeParams(&auto_size_params,
-                                      &resize_guest_params);
+                                      &resize_guest_params,
+                                      was_auto_size_state_dirty);
       } else {
-        GetDamageBufferWithSizeParams(NULL, &resize_guest_params);
+        GetDamageBufferWithSizeParams(NULL,
+                                      &resize_guest_params,
+                                      was_auto_size_state_dirty);
       }
     }
     browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateRect_ACK(
@@ -601,8 +616,10 @@ void BrowserPlugin::OnUpdateRect(
 
 void BrowserPlugin::ParseSizeContraintsChanged() {
   bool auto_size = GetAutoSizeAttribute();
-  if (auto_size)
+  if (auto_size) {
+    is_auto_size_state_dirty_ = true;
     UpdateGuestAutoSizeState(true);
+  }
 }
 
 bool BrowserPlugin::InAutoSizeBounds(const gfx::Size& size) const {
@@ -747,11 +764,11 @@ float BrowserPlugin::GetDeviceScaleFactor() const {
 }
 
 void BrowserPlugin::UpdateDeviceScaleFactor(float device_scale_factor) {
-  if (last_device_scale_factor_ == device_scale_factor || !resize_ack_received_)
+  if (last_device_scale_factor_ == device_scale_factor || !paint_ack_received_)
     return;
 
   BrowserPluginHostMsg_ResizeGuest_Params params;
-  PopulateResizeGuestParameters(&params, plugin_rect());
+  PopulateResizeGuestParameters(&params, plugin_rect(), false);
   browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
       render_view_routing_id_,
       guest_instance_id_,
@@ -860,11 +877,12 @@ void BrowserPlugin::EnableCompositing(bool enable) {
     // We're switching back to the software path. We create a new damage
     // buffer that can accommodate the current size of the container.
     BrowserPluginHostMsg_ResizeGuest_Params params;
-    PopulateResizeGuestParameters(&params, plugin_rect());
     // Request a full repaint from the guest even if its size is not actually
     // changing.
-    params.repaint = true;
-    resize_ack_received_ = false;
+    PopulateResizeGuestParameters(&params,
+                                  plugin_rect(),
+                                  true /* needs_repaint */);
+    paint_ack_received_ = false;
     browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
         render_view_routing_id_,
         guest_instance_id_,
@@ -1008,12 +1026,12 @@ void BrowserPlugin::updateGeometry(
     return;
 
   // In AutoSize mode, guests don't care when the BrowserPlugin container is
-  // resized. If |!resize_ack_received_|, then we are still waiting on a
+  // resized. If |!paint_ack_received_|, then we are still waiting on a
   // previous resize to be ACK'ed and so we don't issue additional resizes
   // until the previous one is ACK'ed.
   // TODO(mthiesse): Assess the performance of calling GetAutoSizeAttribute() on
   // resize.
-  if (!resize_ack_received_ ||
+  if (!paint_ack_received_ ||
       (old_width == window_rect.width && old_height == window_rect.height) ||
       GetAutoSizeAttribute()) {
     // Let the browser know about the updated view rect.
@@ -1023,8 +1041,8 @@ void BrowserPlugin::updateGeometry(
   }
 
   BrowserPluginHostMsg_ResizeGuest_Params params;
-  PopulateResizeGuestParameters(&params, plugin_rect());
-  resize_ack_received_ = false;
+  PopulateResizeGuestParameters(&params, plugin_rect(), false);
+  paint_ack_received_ = false;
   browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
       render_view_routing_id_,
       guest_instance_id_,
@@ -1033,14 +1051,16 @@ void BrowserPlugin::updateGeometry(
 
 void BrowserPlugin::SwapDamageBuffers() {
   current_damage_buffer_.reset(pending_damage_buffer_.release());
-  resize_ack_received_ = true;
+  paint_ack_received_ = true;
 }
 
 void BrowserPlugin::PopulateResizeGuestParameters(
     BrowserPluginHostMsg_ResizeGuest_Params* params,
-    const gfx::Rect& view_rect) {
+    const gfx::Rect& view_rect,
+    bool needs_repaint) {
   params->size_changed = true;
   params->view_rect = view_rect;
+  params->repaint = needs_repaint;
   params->scale_factor = GetDeviceScaleFactor();
   if (last_device_scale_factor_ != params->scale_factor){
     params->repaint = true;
@@ -1071,16 +1091,20 @@ void BrowserPlugin::PopulateResizeGuestParameters(
 
 void BrowserPlugin::GetDamageBufferWithSizeParams(
     BrowserPluginHostMsg_AutoSize_Params* auto_size_params,
-    BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params) {
-  if (auto_size_params)
+    BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params,
+    bool needs_repaint) {
+  if (auto_size_params) {
     PopulateAutoSizeParameters(auto_size_params, GetAutoSizeAttribute());
+  } else {
+    max_auto_size_ = gfx::Size();
+  }
   gfx::Size view_size = (auto_size_params && auto_size_params->enable) ?
       auto_size_params->max_size : gfx::Size(width(), height());
   if (view_size.IsEmpty())
     return;
-  resize_ack_received_ = false;
+  paint_ack_received_ = false;
   gfx::Rect view_rect = gfx::Rect(plugin_rect_.origin(), view_size);
-  PopulateResizeGuestParameters(resize_guest_params, view_rect);
+  PopulateResizeGuestParameters(resize_guest_params, view_rect, needs_repaint);
 }
 
 #if defined(OS_POSIX)
diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h
index 001f2d7..ba30ac9 100644
--- a/content/renderer/browser_plugin/browser_plugin.h
+++ b/content/renderer/browser_plugin/browser_plugin.h
@@ -252,20 +252,22 @@ class CONTENT_EXPORT BrowserPlugin :
   // allocates a new |pending_damage_buffer_| if in software rendering mode.
   void PopulateResizeGuestParameters(
       BrowserPluginHostMsg_ResizeGuest_Params* params,
-      const gfx::Rect& view_size);
+      const gfx::Rect& view_size,
+      bool needs_repaint);
 
   // Populates BrowserPluginHostMsg_AutoSize_Params object with autosize state.
   void PopulateAutoSizeParameters(
-      BrowserPluginHostMsg_AutoSize_Params* params, bool current_auto_size);
+      BrowserPluginHostMsg_AutoSize_Params* params, bool auto_size_enabled);
 
   // Populates both AutoSize and ResizeGuest parameters based on the current
   // autosize state.
   void GetDamageBufferWithSizeParams(
       BrowserPluginHostMsg_AutoSize_Params* auto_size_params,
-      BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params);
+      BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params,
+      bool needs_repaint);
 
   // Informs the guest of an updated autosize state.
-  void UpdateGuestAutoSizeState(bool current_auto_size);
+  void UpdateGuestAutoSizeState(bool auto_size_enabled);
 
   // Indicates whether a damage buffer was used by the guest process for the
   // provided |params|.
@@ -312,14 +314,16 @@ class CONTENT_EXPORT BrowserPlugin :
   scoped_ptr<base::SharedMemory> current_damage_buffer_;
   scoped_ptr<base::SharedMemory> pending_damage_buffer_;
   uint32 damage_buffer_sequence_id_;
-  bool resize_ack_received_;
+  bool paint_ack_received_;
   gfx::Rect plugin_rect_;
   float last_device_scale_factor_;
   // Bitmap for crashed plugin. Lazily initialized, non-owning pointer.
   SkBitmap* sad_guest_;
   bool guest_crashed_;
   scoped_ptr<BrowserPluginHostMsg_ResizeGuest_Params> pending_resize_params_;
-  bool auto_size_ack_pending_;
+  bool is_auto_size_state_dirty_;
+  // Maximum size constraint for autosize.
+  gfx::Size max_auto_size_;
   std::string storage_partition_id_;
   bool persist_storage_;
   bool valid_partition_id_;
-- 
cgit v1.1