summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlazyboy@chromium.org <lazyboy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-15 23:55:04 +0000
committerlazyboy@chromium.org <lazyboy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-15 23:55:04 +0000
commit32deec6509deb789265c50ba2943bc575b7f547c (patch)
treebc0bbbecb4d843daa9bca2808990658440edefaf
parent38fa08719c97f7cd60c3379883488cb50b6fcb73 (diff)
downloadchromium_src-32deec6509deb789265c50ba2943bc575b7f547c.zip
chromium_src-32deec6509deb789265c50ba2943bc575b7f547c.tar.gz
chromium_src-32deec6509deb789265c50ba2943bc575b7f547c.tar.bz2
Make renderer aware of browser plugin position.
We need to send updated screen rects to renderer whenever the embedder's browser side has screen rect updates. This informs webkit/renderer about the correct position of browser plugin. Fix view bounds/coordinates for RWHViewGuest. Both changes together should fix a) datalist/html5 popups appearing in correct position: i. initially, ii: after moving app window, iii: after resizing app window. b) window.screenX/Y/Left/Top for guests as well. BUG=233285, 226653 TEST=Added tests, ran them on trybots. Ran PopupPositioning test in trybot for 50 times on each run, still found few flaky occurrences, will work on it more. Review URL: https://chromiumcodereview.appspot.com/14123006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200393 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/web_view_browsertest.cc8
-rw-r--r--chrome/browser/extensions/web_view_interactive_browsertest.cc140
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning/guest.html57
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.html18
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.js25
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning/manifest.json13
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning/test.js16
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/guest.html60
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.html18
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.js34
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/manifest.json13
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/test.js16
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/guest.html35
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.html17
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.js91
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/manifest.json13
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/test.js7
-rw-r--r--content/browser/browser_plugin/browser_plugin_embedder.cc4
-rw-r--r--content/browser/browser_plugin/browser_plugin_embedder.h4
-rw-r--r--content/browser/browser_plugin/browser_plugin_guest.cc43
-rw-r--r--content/browser/browser_plugin/browser_plugin_guest.h2
-rw-r--r--content/browser/browser_plugin/browser_plugin_guest_manager.cc15
-rw-r--r--content/browser/browser_plugin/browser_plugin_guest_manager.h4
-rw-r--r--content/browser/browser_plugin/test_browser_plugin_guest.cc4
-rw-r--r--content/browser/renderer_host/render_widget_host_delegate.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc2
-rw-r--r--content/browser/renderer_host/render_widget_host_view_guest.cc10
-rw-r--r--content/browser/web_contents/web_contents_impl.cc5
-rw-r--r--content/browser/web_contents/web_contents_impl.h1
-rw-r--r--content/common/browser_plugin/browser_plugin_messages.h9
-rw-r--r--content/renderer/browser_plugin/browser_plugin.cc26
-rw-r--r--content/renderer/browser_plugin/browser_plugin.h3
-rw-r--r--content/renderer/browser_plugin/browser_plugin_browsertest.cc23
33 files changed, 701 insertions, 38 deletions
diff --git a/chrome/browser/extensions/web_view_browsertest.cc b/chrome/browser/extensions/web_view_browsertest.cc
index e8a3ed8..4d830c5 100644
--- a/chrome/browser/extensions/web_view_browsertest.cc
+++ b/chrome/browser/extensions/web_view_browsertest.cc
@@ -890,6 +890,14 @@ IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_MediaAccessAPIAllow) {
}
}
+// Checks that window.screenX/screenY/screenLeft/screenTop works correctly for
+// guests.
+IN_PROC_BROWSER_TEST_F(WebViewTest, ScreenCoordinates) {
+ ASSERT_TRUE(StartTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/screen_coordinates"))
+ << message_;
+}
+
IN_PROC_BROWSER_TEST_F(WebViewTest, SpeechRecognition) {
ASSERT_TRUE(StartTestServer());
content::WebContents* guest_web_contents = LoadGuest(
diff --git a/chrome/browser/extensions/web_view_interactive_browsertest.cc b/chrome/browser/extensions/web_view_interactive_browsertest.cc
index 8ad9ace..88e1fa23 100644
--- a/chrome/browser/extensions/web_view_interactive_browsertest.cc
+++ b/chrome/browser/extensions/web_view_interactive_browsertest.cc
@@ -12,6 +12,8 @@
#include "chrome/test/base/ui_controls.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/test/browser_test_utils.h"
@@ -86,8 +88,8 @@ class WebViewInteractiveTest
void SetupTest(const std::string& app_name,
const std::string& guest_url_spec) {
ASSERT_TRUE(StartTestServer());
- std::string host_str("localhost"); // Must stay in scope with replace_host.
GURL::Replacements replace_host;
+ std::string host_str("localhost"); // Must stay in scope with replace_host.
replace_host.SetHostStr(host_str);
GURL guest_url = test_server()->GetURL(guest_url_spec);
@@ -128,6 +130,116 @@ class WebViewInteractiveTest
return corner_;
}
+ void SimulateRWHMouseClick(content::RenderWidgetHost* rwh, int x, int y) {
+ WebKit::WebMouseEvent mouse_event;
+ mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
+ mouse_event.x = mouse_event.windowX = x;
+ mouse_event.y = mouse_event.windowY = y;
+ mouse_event.modifiers = 0;
+
+ mouse_event.type = WebKit::WebInputEvent::MouseDown;
+ rwh->ForwardMouseEvent(mouse_event);
+ mouse_event.type = WebKit::WebInputEvent::MouseUp;
+ rwh->ForwardMouseEvent(mouse_event);
+ }
+
+ class PopupCreatedObserver {
+ public:
+ PopupCreatedObserver() : created_(false), last_render_widget_host_(NULL) {
+ created_callback_ = base::Bind(
+ &PopupCreatedObserver::CreatedCallback, base::Unretained(this));
+ content::RenderWidgetHost::AddCreatedCallback(created_callback_);
+ }
+ virtual ~PopupCreatedObserver() {
+ content::RenderWidgetHost::RemoveCreatedCallback(created_callback_);
+ }
+ void Reset() {
+ created_ = false;
+ }
+ void Start() {
+ if (created_)
+ return;
+ message_loop_ = new content::MessageLoopRunner;
+ message_loop_->Run();
+ }
+ content::RenderWidgetHost* last_render_widget_host() {
+ return last_render_widget_host_;
+ }
+
+ private:
+ void CreatedCallback(content::RenderWidgetHost* rwh) {
+ last_render_widget_host_ = rwh;
+ if (message_loop_)
+ message_loop_->Quit();
+ else
+ created_ = true;
+ }
+ content::RenderWidgetHost::CreatedCallback created_callback_;
+ scoped_refptr<content::MessageLoopRunner> message_loop_;
+ bool created_;
+ content::RenderWidgetHost* last_render_widget_host_;
+ };
+
+ void WaitForTitle(const char* title) {
+ string16 expected_title(ASCIIToUTF16(title));
+ string16 error_title(ASCIIToUTF16("FAILED"));
+ content::TitleWatcher title_watcher(guest_web_contents(), expected_title);
+ title_watcher.AlsoWaitForTitle(error_title);
+ ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+ }
+
+ void PopupTestHelper(const gfx::Point& padding) {
+ PopupCreatedObserver popup_created_observer;
+ popup_created_observer.Reset();
+
+ content::SimulateKeyPress(
+ guest_web_contents(),
+ ui::VKEY_C, // C to autocomplete.
+ false, false, false, false);
+
+ WaitForTitle("PASSED1");
+
+ popup_created_observer.Start();
+
+ content::RenderWidgetHost* popup_rwh = NULL;
+ popup_rwh = popup_created_observer.last_render_widget_host();
+ // Popup must be present.
+ ASSERT_TRUE(popup_rwh);
+ ASSERT_TRUE(!popup_rwh->IsRenderView());
+ ASSERT_TRUE(popup_rwh->GetView());
+
+ string16 expected_title = ASCIIToUTF16("PASSED2");
+ string16 error_title = ASCIIToUTF16("FAILED");
+ content::TitleWatcher title_watcher(guest_web_contents(), expected_title);
+ title_watcher.AlsoWaitForTitle(error_title);
+ EXPECT_TRUE(content::ExecuteScript(guest_web_contents(),
+ "changeTitle();"));
+ ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ gfx::Rect popup_bounds = popup_rwh->GetView()->GetViewBounds();
+ // (2, 2) is expected to lie on the first datalist element.
+ SimulateRWHMouseClick(popup_rwh, 2, 2);
+
+ content::RenderViewHost* embedder_rvh =
+ GetFirstShellWindowWebContents()->GetRenderViewHost();
+ gfx::Rect embedder_bounds = embedder_rvh->GetView()->GetViewBounds();
+ gfx::Vector2d diff = popup_bounds.origin() - embedder_bounds.origin();
+ LOG(INFO) << "DIFF: x = " << diff.x() << ", y = " << diff.y();
+
+ const int left_spacing = 40 + padding.x(); // div.style.paddingLeft = 40px.
+ // div.style.paddingTop = 50px + (input box height = 26px).
+ const int top_spacing = 50 + 26 + padding.y();
+
+ // If the popup is placed within |threshold_px| of the expected position,
+ // then we consider the test as a pass.
+ const int threshold_px = 10;
+
+ EXPECT_LE(std::abs(diff.x() - left_spacing), threshold_px);
+ EXPECT_LE(std::abs(diff.y() - top_spacing), threshold_px);
+
+ WaitForTitle("PASSED3");
+ }
+
private:
content::WebContents* guest_web_contents_;
content::WebContents* embedder_web_contents_;
@@ -250,3 +362,29 @@ IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) {
ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/execute_code"))
<< message_;
}
+
+IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PopupPositioning) {
+ SetupTest(
+ "web_view/popup_positioning",
+ "files/extensions/platform_apps/web_view/popup_positioning/guest.html");
+ ASSERT_TRUE(guest_web_contents());
+
+ PopupTestHelper(gfx::Point());
+
+ // moveTo a random location and run the steps again.
+ EXPECT_TRUE(content::ExecuteScript(embedder_web_contents(),
+ "window.moveTo(16, 20);"));
+ PopupTestHelper(gfx::Point());
+}
+
+// Tests that moving browser plugin (without resize/UpdateRects) correctly
+// repositions popup.
+IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PopupPositioningMoved) {
+ SetupTest(
+ "web_view/popup_positioning_moved",
+ "files/extensions/platform_apps/web_view/popup_positioning_moved"
+ "/guest.html");
+ ASSERT_TRUE(guest_web_contents());
+
+ PopupTestHelper(gfx::Point(20, 0));
+}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/guest.html b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/guest.html
new file mode 100644
index 0000000..2e08d33
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/guest.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<!--
+ * 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>
+<head>
+ <title>WAITING</title>
+ <style type="text/css">
+ body { margin: 0; padding: 0; }
+ </style>
+</head>
+<body>
+ <div>
+ <input type="text" list="items" style="height: 20px;"/>
+ <datalist id="items">
+ <option value="Chromium"></option>
+ <option value="ChromiumB"></option>
+ <option value="ChromiumC"></option>
+ <option value="Molybdenum"></option>
+ <option value="Seaborgium"></option>
+ <option value="Tungsten"></option>
+ </datalist>
+ </div>
+
+ <script>
+ // TODO(lazyboy): Apps do not support <input> + datalist with id attribute.
+ var inputElement = document.querySelector('input');
+ var step = 1;
+
+ var onInput = function(e) {
+ var value = inputElement.value;
+ window.console.log('onInput, value: ' + value);
+ if (step == 1) {
+ document.title = 'PASSED1';
+ } else if (step == 2) {
+ if (value == 'Chromium') {
+ inputElement.value = '';
+ document.title = 'PASSED3';
+ step = 0;
+ } else {
+ document.title = 'FAILED';
+ }
+ }
+ ++step;
+ };
+
+ inputElement.oninput = onInput;
+ inputElement.focus();
+
+ window['changeTitle'] = function() {
+ window.setTimeout(function() { document.title = 'PASSED2'; }, 0);
+ };
+ </script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.html b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.html
new file mode 100644
index 0000000..4cfc4fb
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<!--
+ * 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>
+<head>
+<style type="text/css">
+body { margin:0; padding:0; }
+</style>
+</head>
+<body>
+ <div id="webview-tag-container"
+ style="padding-left: 40px; padding-top: 60px;"></div>
+ <script src="main.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.js b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.js
new file mode 100644
index 0000000..eb11e9f
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/main.js
@@ -0,0 +1,25 @@
+// 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.
+
+var startTest = function() {
+ chrome.test.sendMessage('connected');
+};
+
+chrome.test.getConfig(function(config) {
+ var guestURL = 'http://localhost:' + config.testServer.port +
+ '/files/extensions/platform_apps/web_view/popup_positioning/guest.html';
+ var webview = document.createElement('webview');
+ var loaded = false;
+ webview.addEventListener('loadstop', function(e) {
+ window.console.log('webview.loadstop');
+ if (!loaded) {
+ loaded = true;
+ startTest();
+ }
+ });
+ webview.style.width = '200px';
+ webview.style.height = '200px';
+ webview.setAttribute('src', guestURL);
+ document.querySelector('#webview-tag-container').appendChild(webview);
+});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/manifest.json
new file mode 100644
index 0000000..f093c67
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/manifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "<webview> html5 popup.",
+ "description": "Test that checks popup positioning correctness",
+ "version": "1",
+ "permissions": [
+ "webview"
+ ],
+ "app": {
+ "background": {
+ "scripts": ["test.js"]
+ }
+ }
+}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/test.js b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/test.js
new file mode 100644
index 0000000..8c4cd9b
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning/test.js
@@ -0,0 +1,16 @@
+// 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', {
+ bounds: {
+ width: 400,
+ height: 400,
+ // Prefer close to top left on screen so we have enough space for
+ // rendering popup.
+ left: 20,
+ top: 20
+ }
+ }, function (win) {});
+});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/guest.html b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/guest.html
new file mode 100644
index 0000000..6741085
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/guest.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<!--
+ * 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>
+<head>
+ <title>WAITING</title>
+ <style type="text/css">
+ body { margin: 0; padding: 0; }
+ </style>
+</head>
+<body>
+ <div>
+ <input type="text" list="items" style="height: 20px;"/>
+ <datalist id="items">
+ <option value="Chromium"></option>
+ <option value="ChromiumB"></option>
+ <option value="ChromiumC"></option>
+ <option value="Molybdenum"></option>
+ <option value="Seaborgium"></option>
+ <option value="Tungsten"></option>
+ </datalist>
+ </div>
+
+ <script>
+ var inputElement = document.querySelector('input');
+ var step = 1;
+
+ var onInput = function(e) {
+ var value = inputElement.value;
+ window.console.log('onInput, value: ' + value + ', step = ' + step);
+ if (step == 1) {
+ // TODO(lazyboy): We don't have a way to reliably wait for a
+ // RenderWidgetHost to be added to a WebContents, hence the 500ms
+ // timeout below. Bad, fix.
+ window.setTimeout(function() {
+ document.title = 'PASSED1';
+ }, 500);
+ } else if (step == 2) {
+ if (value == 'Chromium') {
+ inputElement.value = '';
+ document.title = 'PASSED3';
+ } else {
+ document.title = 'FAILED';
+ }
+ }
+ ++step;
+ };
+
+ window['changeTitle'] = function() {
+ window.setTimeout(function() { document.title = 'PASSED2'; }, 0);
+ };
+
+ inputElement.oninput = onInput;
+ inputElement.focus();
+ </script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.html b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.html
new file mode 100644
index 0000000..4cfc4fb
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<!--
+ * 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>
+<head>
+<style type="text/css">
+body { margin:0; padding:0; }
+</style>
+</head>
+<body>
+ <div id="webview-tag-container"
+ style="padding-left: 40px; padding-top: 60px;"></div>
+ <script src="main.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.js b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.js
new file mode 100644
index 0000000..870bbc7
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/main.js
@@ -0,0 +1,34 @@
+// 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.
+
+var startTest = function() {
+ chrome.test.sendMessage('connected');
+};
+
+chrome.test.getConfig(function(config) {
+ var guestURL = 'http://localhost:' + config.testServer.port +
+ '/files/extensions/platform_apps/web_view/popup_positioning_moved' +
+ '/guest.html';
+ var webview = document.createElement('webview');
+ var loaded = false;
+
+
+ var onWebViewLoadStop = function(e) {
+ window.console.log('webview.loadstop');
+ if (loaded) {
+ return;
+ }
+ loaded = true;
+ // We move the <webview> in a way, this would trigger
+ // BrowserPlugin::updateGeometry but no UpdateRects.
+ webview.style.paddingLeft = '20px';
+ startTest();
+ };
+ webview.addEventListener('loadstop', onWebViewLoadStop);
+
+ webview.style.width = '200px';
+ webview.style.height = '200px';
+ webview.setAttribute('src', guestURL);
+ document.querySelector('#webview-tag-container').appendChild(webview);
+});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/manifest.json
new file mode 100644
index 0000000..68e79f7
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/manifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "<webview> html5 popup + move.",
+ "description": "Test that checks popup positioning correctness after moving plugin",
+ "version": "1",
+ "permissions": [
+ "webview"
+ ],
+ "app": {
+ "background": {
+ "scripts": ["test.js"]
+ }
+ }
+}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/test.js b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/test.js
new file mode 100644
index 0000000..8c4cd9b
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/popup_positioning_moved/test.js
@@ -0,0 +1,16 @@
+// 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', {
+ bounds: {
+ width: 400,
+ height: 400,
+ // Prefer close to top left on screen so we have enough space for
+ // rendering popup.
+ left: 20,
+ top: 20
+ }
+ }, function (win) {});
+});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/guest.html b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/guest.html
new file mode 100644
index 0000000..a2b2ac2
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/guest.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<!--
+ * 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>
+ <head>
+ <script type="text/javascript">
+ // Notifies the embedder about the result of the request (success/fail)
+ // via post message. Note that the embedder has to initiate a postMessage
+ // first so that guest has a reference to the embedder's window.
+ var onPostMessageReceived = function(e) {
+ var data = JSON.parse(e.data);
+ if (data[0] == 'test1') {
+ var screenInfo = {
+ 'screenX': window.screenX,
+ 'screenY': window.screenY,
+ 'screenLeft': window.screenLeft,
+ 'screenTop': window.screenTop
+ };
+ var responseArray = [];
+ responseArray.push(data[0]);
+ responseArray.push(screenInfo);
+ e.source.postMessage(JSON.stringify(responseArray), '*');
+
+ }
+ };
+ window.addEventListener('message', onPostMessageReceived, false);
+ </script>
+ </head>
+ <body>
+ <div>This is guest</div>
+ </body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.html b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.html
new file mode 100644
index 0000000..d1ec7d8
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<!--
+ * 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>
+<head>
+<style type="text/css">
+ body { margin: 0; padding: 0; }
+</style>
+</head>
+<body>
+ <div id="webview-tag-container"></div>
+ <script src="main.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.js b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.js
new file mode 100644
index 0000000..43483c1
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/main.js
@@ -0,0 +1,91 @@
+// 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.
+
+var embedder = {};
+embedder.tests = {};
+embedder.baseGuestURL = '';
+embedder.guestURL = '';
+
+embedder.setUp = function(config) {
+ embedder.baseGuestURL = 'http://localhost:' + config.testServer.port;
+ embedder.guestURL = embedder.baseGuestURL +
+ '/files/extensions/platform_apps/web_view/screen_coordinates' +
+ '/guest.html';
+ chrome.test.log('Guest url is: ' + embedder.guestURL);
+};
+
+/** @private */
+embedder.setUpGuest_ = function() {
+ document.querySelector('#webview-tag-container').innerHTML =
+ '<webview style="width: 100px; height: 100px;"' +
+ ' src="' + embedder.guestURL + '"' +
+ '></webview>';
+ var webview = document.querySelector('webview');
+ if (!webview) {
+ chrome.test.fail('No <webview> element created');
+ }
+ return webview;
+};
+
+/** @private */
+embedder.setUpLoadStop_ = function(webview, testName) {
+ var onWebViewLoadStop = function(e) {
+ // Send post message to <webview> when it's ready to receive them.
+ webview.contentWindow.postMessage(
+ JSON.stringify(['' + testName, 'get-screen-info']), '*');
+ };
+ webview.addEventListener('loadstop', onWebViewLoadStop);
+};
+
+/**
+ * @private
+ * @param {Number} mn Expected range's min value.
+ * @param {Number} mx Expected range's max value.
+ * @param {Number} a Actual value.
+ */
+embedder.assertCorrectCoordinateValue_ = function(mn, mx, a, msg) {
+ chrome.test.assertTrue(
+ a >= mn && a <= mx,
+ 'Actual value [' + a + '] is not within interval ' +
+ '[' + mn + ', ' + mx + ']');
+};
+
+/** @private */
+embedder.registerAndWaitForPostMessage_ = function(
+ webview, expectedData) {
+ var testName = expectedData[0];
+ var onPostMessageReceived = function(e) {
+ var data = JSON.parse(e.data);
+ if (data[0] == '' + testName) {
+ embedder.assertCorrectCoordinateValue_(
+ window.screenX, window.screenX + window.innerWidth,
+ data[1].screenX, 'screenX');
+ embedder.assertCorrectCoordinateValue_(
+ window.screenY, window.screenY + window.innerHeight,
+ data[1].screenY, 'screenY');
+ embedder.assertCorrectCoordinateValue_(
+ window.screenLeft, window.screenLeft + window.innerWidth,
+ data[1].screenLeft, 'screenLeft');
+ embedder.assertCorrectCoordinateValue_(
+ window.screenTop, window.screenTop + window.innerHeight,
+ data[1].screenTop, 'screenTop');
+ chrome.test.succeed();
+ }
+ };
+ window.addEventListener('message', onPostMessageReceived);
+};
+
+
+onload = function() {
+ chrome.test.getConfig(function(config) {
+ embedder.setUp(config);
+ chrome.test.runTests([
+ function testScreenCoordinates() {
+ var webview = embedder.setUpGuest_();
+ embedder.setUpLoadStop_(webview, 'test1');
+ embedder.registerAndWaitForPostMessage_(webview, ['test1']);
+ }
+ ]);
+ });
+};
diff --git a/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/manifest.json
new file mode 100644
index 0000000..7234400
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/manifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "<webview> Guest screenX/Y",
+ "description": "Test that checks window.screenX/Y correctness for guest.",
+ "version": "1",
+ "permissions": [
+ "webview"
+ ],
+ "app": {
+ "background": {
+ "scripts": ["test.js"]
+ }
+ }
+}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/test.js b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/test.js
new file mode 100644
index 0000000..2f9f855
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/screen_coordinates/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/content/browser/browser_plugin/browser_plugin_embedder.cc b/content/browser/browser_plugin/browser_plugin_embedder.cc
index 12de8ef..ba8b10a 100644
--- a/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -75,6 +75,10 @@ void BrowserPluginEmbedder::GetRenderViewHostAtPosition(
++next_get_render_view_request_id_;
}
+void BrowserPluginEmbedder::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
+ GetBrowserPluginGuestManager()->DidSendScreenRects(web_contents(), rwh);
+}
+
void BrowserPluginEmbedder::RenderViewGone(base::TerminationStatus status) {
CleanUp();
}
diff --git a/content/browser/browser_plugin/browser_plugin_embedder.h b/content/browser/browser_plugin/browser_plugin_embedder.h
index 1b6c8b2..3dbb3f3 100644
--- a/content/browser/browser_plugin/browser_plugin_embedder.h
+++ b/content/browser/browser_plugin/browser_plugin_embedder.h
@@ -33,6 +33,7 @@ namespace content {
class BrowserPluginGuest;
class BrowserPluginGuestManager;
class BrowserPluginHostFactory;
+class RenderWidgetHostImpl;
class WebContentsImpl;
class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
@@ -49,6 +50,9 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
int y,
const WebContents::GetRenderViewHostCallback& callback);
+ // Called when embedder's |rwh| has sent screen rects to renderer.
+ void DidSendScreenRects(RenderWidgetHostImpl* rwh);
+
// Overrides factory for testing. Default (NULL) value indicates regular
// (non-test) environment.
static void set_factory_for_testing(BrowserPluginHostFactory* factory) {
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index ea8ce65..d1c6caa 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -356,6 +356,7 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Stop, OnStop)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_TerminateGuest, OnTerminateGuest)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK, OnUpdateRectACK)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -367,6 +368,8 @@ void BrowserPluginGuest::Initialize(
const BrowserPluginHostMsg_Attach_Params& params) {
focused_ = params.focused;
guest_visible_ = params.visible;
+ guest_window_rect_ = params.resize_guest_params.view_rect;
+
if (!params.name.empty())
name_ = params.name;
auto_size_enabled_ = params.auto_size_params.enable;
@@ -472,6 +475,13 @@ void BrowserPluginGuest::UpdateVisibility() {
OnSetVisibility(instance_id_, visible());
}
+// screen.
+gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
+ gfx::Rect guest_rect(bounds);
+ guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
+ return guest_rect;
+}
+
void BrowserPluginGuest::Observe(int type,
const NotificationSource& source,
const NotificationDetails& details) {
@@ -667,7 +677,7 @@ void BrowserPluginGuest::SetDamageBuffer(
DCHECK(*static_cast<unsigned int*>(damage_buffer_->memory()) == 0xdeadbeef);
damage_buffer_sequence_id_ = params.damage_buffer_sequence_id;
damage_buffer_size_ = params.damage_buffer_size;
- damage_view_size_ = params.view_size;
+ damage_view_size_ = params.view_rect.size();
damage_buffer_scale_factor_ = params.scale_factor;
}
@@ -972,6 +982,7 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
case BrowserPluginHostMsg_Stop::ID:
case BrowserPluginHostMsg_TerminateGuest::ID:
case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
+ case BrowserPluginHostMsg_UpdateGeometry::ID:
case BrowserPluginHostMsg_UpdateRect_ACK::ID:
return true;
default:
@@ -1251,16 +1262,16 @@ void BrowserPluginGuest::OnResizeGuest(
// Invalid damage buffer means we are in HW compositing mode,
// so just resize the WebContents and repaint if needed.
if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) {
- if (!params.view_size.IsEmpty())
- GetWebContents()->GetView()->SizeContents(params.view_size);
+ if (!params.view_rect.size().IsEmpty())
+ GetWebContents()->GetView()->SizeContents(params.view_rect.size());
if (params.repaint)
- Send(new ViewMsg_Repaint(routing_id(), params.view_size));
+ Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
return;
}
SetDamageBuffer(params);
- GetWebContents()->GetView()->SizeContents(params.view_size);
+ GetWebContents()->GetView()->SizeContents(params.view_rect.size());
if (params.repaint)
- Send(new ViewMsg_Repaint(routing_id(), params.view_size));
+ Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
}
void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
@@ -1304,7 +1315,7 @@ void BrowserPluginGuest::OnSetSize(
Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
} else if (!auto_size_enabled_ && old_auto_size_enabled) {
GetWebContents()->GetRenderViewHost()->DisableAutoResize(
- resize_guest_params.view_size);
+ resize_guest_params.view_rect.size());
}
OnResizeGuest(instance_id_, resize_guest_params);
}
@@ -1386,6 +1397,17 @@ void BrowserPluginGuest::OnUpdateRectACK(
OnSetSize(instance_id_, auto_size_params, resize_guest_params);
}
+void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
+ const gfx::Rect& view_rect) {
+ // The plugin has moved within the embedder without resizing or the
+ // embedder/container's view rect changing.
+ guest_window_rect_ = view_rect;
+ RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
+ GetWebContents()->GetRenderViewHost());
+ if (rvh)
+ rvh->SendScreenRects();
+}
+
void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
SendMessageToEmbedder(
new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
@@ -1415,9 +1437,7 @@ void BrowserPluginGuest::OnShowPopup(
void BrowserPluginGuest::OnShowWidget(int route_id,
const gfx::Rect& initial_pos) {
- gfx::Rect screen_pos(initial_pos);
- screen_pos.Offset(guest_screen_rect_.OffsetFromOrigin());
- GetWebContents()->ShowCreatedWidget(route_id, screen_pos);
+ GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
}
void BrowserPluginGuest::OnTakeFocus(bool reverse) {
@@ -1482,8 +1502,7 @@ void BrowserPluginGuest::OnUpdateRect(
// The scaling change can happen due to asynchronous updates of the DPI on a
// resolution change.
if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) ||
- (params.view_size.width() == damage_view_size().width() &&
- params.view_size.height() == damage_view_size().height())) &&
+ (params.view_size == damage_view_size())) &&
params.scale_factor == damage_buffer_scale_factor()) {
TransportDIB* dib = GetWebContents()->GetRenderProcessHost()->
GetTransportDIB(params.bitmap);
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h
index 155d9f3..a298922 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -254,6 +254,7 @@ class CONTENT_EXPORT BrowserPluginGuest
// Returns whether BrowserPluginGuest is interested in receiving the given
// |message|.
static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
+ gfx::Rect ToGuestRect(const gfx::Rect& rect);
void DragSourceEndedAt(int client_x, int client_y, int screen_x,
int screen_y, WebKit::WebDragOperation operation);
@@ -391,6 +392,7 @@ class CONTENT_EXPORT BrowserPluginGuest
void OnTerminateGuest(int instance_id);
void OnUnlockMouse();
void OnUnlockMouseAck(int instance_id);
+ void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect);
void OnUpdateRectACK(
int instance_id,
const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
diff --git a/content/browser/browser_plugin/browser_plugin_guest_manager.cc b/content/browser/browser_plugin/browser_plugin_guest_manager.cc
index 081f332..1a33e9a 100644
--- a/content/browser/browser_plugin/browser_plugin_guest_manager.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest_manager.cc
@@ -230,4 +230,19 @@ void BrowserPluginGuestManager::OnUnhandledSwapBuffersACK(
sync_point);
}
+void BrowserPluginGuestManager::DidSendScreenRects(
+ WebContents* embedder_web_contents, RenderWidgetHostImpl* rwh) {
+ // TODO(lazyboy): Generalize iterating over guest instances and performing
+ // actions on the guests.
+ for (GuestInstanceMap::iterator it =
+ guest_web_contents_by_instance_id_.begin();
+ it != guest_web_contents_by_instance_id_.end(); ++it) {
+ BrowserPluginGuest* guest = it->second->GetBrowserPluginGuest();
+ if (embedder_web_contents == guest->embedder_web_contents()) {
+ static_cast<RenderViewHostImpl*>(
+ guest->GetWebContents()->GetRenderViewHost())->SendScreenRects();
+ }
+ }
+}
+
} // namespace content
diff --git a/content/browser/browser_plugin/browser_plugin_guest_manager.h b/content/browser/browser_plugin/browser_plugin_guest_manager.h
index 4e1ba28..f915362 100644
--- a/content/browser/browser_plugin/browser_plugin_guest_manager.h
+++ b/content/browser/browser_plugin/browser_plugin_guest_manager.h
@@ -31,6 +31,7 @@ namespace content {
class BrowserPluginGuest;
class BrowserPluginHostFactory;
class RenderProcessHostImpl;
+class RenderWidgetHostImpl;
class SiteInstance;
class WebContents;
class WebContentsImpl;
@@ -79,6 +80,9 @@ class CONTENT_EXPORT BrowserPluginGuestManager :
bool CanEmbedderAccessInstanceIDMaybeKill(int embedder_render_process_id,
int instance_id) const;
+ void DidSendScreenRects(WebContents* embedder_web_contents,
+ RenderWidgetHostImpl* rwh);
+
void OnMessageReceived(const IPC::Message& message, int render_process_id);
private:
diff --git a/content/browser/browser_plugin/test_browser_plugin_guest.cc b/content/browser/browser_plugin/test_browser_plugin_guest.cc
index 083ea5a..5205752 100644
--- a/content/browser/browser_plugin/test_browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/test_browser_plugin_guest.cc
@@ -265,10 +265,10 @@ void TestBrowserPluginGuest::OnStop(int instance_id) {
void TestBrowserPluginGuest::SetDamageBuffer(
const BrowserPluginHostMsg_ResizeGuest_Params& params) {
++damage_buffer_call_count_;
- last_damage_buffer_size_ = params.view_size;
+ last_damage_buffer_size_ = params.view_rect.size();
if (waiting_for_damage_buffer_with_size_ &&
- expected_damage_buffer_size_ == params.view_size &&
+ expected_damage_buffer_size_ == params.view_rect.size() &&
damage_buffer_message_loop_runner_) {
damage_buffer_message_loop_runner_->Quit();
waiting_for_damage_buffer_with_size_ = false;
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index fa41727..9e8d36e 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -46,6 +46,9 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Returns true if the |event| was handled.
virtual bool PreHandleWheelEvent(const WebKit::WebMouseWheelEvent& event);
+ // Notifies that screen rects were sent to renderer process.
+ virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) {}
+
#if defined(OS_WIN) && defined(USE_AURA)
// Returns the widget's parent's NativeViewAccessible.
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 5c09f18..87d8aa0 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -318,6 +318,8 @@ void RenderWidgetHostImpl::SendScreenRects() {
last_window_screen_rect_ = view_->GetBoundsInRootWindow();
Send(new ViewMsg_UpdateScreenRects(
GetRoutingID(), last_view_screen_rect_, last_window_screen_rect_));
+ if (delegate_)
+ delegate_->DidSendScreenRects(this);
waiting_for_screen_rects_ack_ = true;
}
diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc
index 6f02367..2e00453 100644
--- a/content/browser/renderer_host/render_widget_host_view_guest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_guest.cc
@@ -81,7 +81,8 @@ void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
}
gfx::Rect RenderWidgetHostViewGuest::GetBoundsInRootWindow() {
- return gfx::Rect(size_);
+ // We do not have any root window specific parts in this view.
+ return GetViewBounds();
}
gfx::GLSurfaceHandle RenderWidgetHostViewGuest::GetCompositingSurface() {
@@ -125,7 +126,12 @@ bool RenderWidgetHostViewGuest::IsShowing() {
}
gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
- return gfx::Rect(size_);
+ gfx::Rect embedder_bounds = static_cast<RenderWidgetHostViewPort*>(
+ guest_->GetEmbedderRenderWidgetHostView())->GetViewBounds();
+ gfx::Rect shifted_rect = guest_->ToGuestRect(embedder_bounds);
+ shifted_rect.set_width(size_.width());
+ shifted_rect.set_height(size_.height());
+ return shifted_rect;
}
void RenderWidgetHostViewGuest::RenderViewGone(base::TerminationStatus status,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 4969576..d8e4d6e2 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1596,6 +1596,11 @@ void WebContentsImpl::RequestMediaAccessPermission(
callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
}
+void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
+ if (browser_plugin_embedder_)
+ browser_plugin_embedder_->DidSendScreenRects(rwh);
+}
+
void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
preferred_size_ = pref_size;
if (delegate_)
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 3cca074..529b363 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -448,6 +448,7 @@ class CONTENT_EXPORT WebContentsImpl
const NativeWebKeyboardEvent& event) OVERRIDE;
virtual bool PreHandleWheelEvent(
const WebKit::WebMouseWheelEvent& event) OVERRIDE;
+ virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) OVERRIDE;
#if defined(OS_WIN) && defined(USE_AURA)
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
#endif
diff --git a/content/common/browser_plugin/browser_plugin_messages.h b/content/common/browser_plugin/browser_plugin_messages.h
index f10453b..61c970d 100644
--- a/content/common/browser_plugin/browser_plugin_messages.h
+++ b/content/common/browser_plugin/browser_plugin_messages.h
@@ -50,8 +50,8 @@ IPC_STRUCT_BEGIN(BrowserPluginHostMsg_ResizeGuest_Params)
IPC_STRUCT_MEMBER(base::SharedMemoryHandle, damage_buffer_handle)
// The size of the damage buffer.
IPC_STRUCT_MEMBER(size_t, damage_buffer_size)
- // The new size of the guest view area.
- IPC_STRUCT_MEMBER(gfx::Size, view_size)
+ // The new rect of the guest view area.
+ IPC_STRUCT_MEMBER(gfx::Rect, view_rect)
// Indicates the scale factor of the embedder WebView.
IPC_STRUCT_MEMBER(float, scale_factor)
// Indicates a request for a full repaint of the page.
@@ -284,6 +284,11 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_LockMouse_ACK,
// Sends a PointerLock Unlock ACK to the BrowserPluginGuest.
IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_UnlockMouse_ACK, int /* instance_id */)
+// Sent when plugin's position has changed without UpdateRect.
+IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_UpdateGeometry,
+ int /* instance_id */,
+ gfx::Rect /* view_rect */)
+
// -----------------------------------------------------------------------------
// These messages are from the guest renderer to the browser process
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index d3aa325..46b9ec4 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -922,7 +922,7 @@ void BrowserPlugin::UpdateDeviceScaleFactor(float device_scale_factor) {
return;
BrowserPluginHostMsg_ResizeGuest_Params params;
- PopulateResizeGuestParameters(&params, gfx::Size(width(), height()));
+ PopulateResizeGuestParameters(&params, plugin_rect());
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
render_view_routing_id_,
instance_id_,
@@ -1166,7 +1166,7 @@ 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, gfx::Size(width(), height()));
+ PopulateResizeGuestParameters(&params, plugin_rect());
// Request a full repaint from the guest even if its size is not actually
// changing.
params.repaint = true;
@@ -1307,21 +1307,26 @@ void BrowserPlugin::updateGeometry(
int old_width = width();
int old_height = height();
plugin_rect_ = window_rect;
+ if (!HasGuest())
+ 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
// 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 (!HasGuest() ||
- !resize_ack_received_ ||
+ if (!resize_ack_received_ ||
(old_width == window_rect.width && old_height == window_rect.height) ||
GetAutoSizeAttribute()) {
+ // Let the browser know about the updated view rect.
+ browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateGeometry(
+ render_view_routing_id_, instance_id_, plugin_rect_));
return;
}
BrowserPluginHostMsg_ResizeGuest_Params params;
- PopulateResizeGuestParameters(&params, gfx::Size(width(), height()));
+ PopulateResizeGuestParameters(&params, plugin_rect());
resize_ack_received_ = false;
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
render_view_routing_id_,
@@ -1336,8 +1341,8 @@ void BrowserPlugin::SwapDamageBuffers() {
void BrowserPlugin::PopulateResizeGuestParameters(
BrowserPluginHostMsg_ResizeGuest_Params* params,
- const gfx::Size& view_size) {
- params->view_size = view_size;
+ const gfx::Rect& view_rect) {
+ params->view_rect = view_rect;
params->scale_factor = GetDeviceScaleFactor();
if (last_device_scale_factor_ != params->scale_factor){
params->repaint = true;
@@ -1348,12 +1353,12 @@ void BrowserPlugin::PopulateResizeGuestParameters(
if (compositing_enabled_)
return;
- const size_t stride = skia::PlatformCanvasStrideForWidth(view_size.width());
+ const size_t stride = skia::PlatformCanvasStrideForWidth(view_rect.width());
// Make sure the size of the damage buffer is at least four bytes so that we
// can fit in a magic word to verify that the memory is shared correctly.
size_t size =
std::max(sizeof(unsigned int),
- static_cast<size_t>(view_size.height() *
+ static_cast<size_t>(view_rect.height() *
stride *
GetDeviceScaleFactor() *
GetDeviceScaleFactor()));
@@ -1376,7 +1381,8 @@ void BrowserPlugin::GetDamageBufferWithSizeParams(
if (view_size.IsEmpty())
return;
resize_ack_received_ = false;
- PopulateResizeGuestParameters(resize_guest_params, view_size);
+ gfx::Rect view_rect = gfx::Rect(plugin_rect_.origin(), view_size);
+ PopulateResizeGuestParameters(resize_guest_params, view_rect);
}
#if defined(OS_POSIX)
diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h
index 72c618c..3d7ee9a 100644
--- a/content/renderer/browser_plugin/browser_plugin.h
+++ b/content/renderer/browser_plugin/browser_plugin.h
@@ -239,6 +239,7 @@ class CONTENT_EXPORT BrowserPlugin :
int width() const { return plugin_rect_.width(); }
int height() const { return plugin_rect_.height(); }
+ gfx::Rect plugin_rect() { return plugin_rect_; }
// Gets the Max Height value used for auto size.
int GetAdjustedMaxHeight() const;
// Gets the Max Width value used for auto size.
@@ -274,7 +275,7 @@ class CONTENT_EXPORT BrowserPlugin :
// allocates a new |pending_damage_buffer_| if in software rendering mode.
void PopulateResizeGuestParameters(
BrowserPluginHostMsg_ResizeGuest_Params* params,
- const gfx::Size& view_size);
+ const gfx::Rect& view_size);
// Populates BrowserPluginHostMsg_AutoSize_Params object with autosize state.
void PopulateAutoSizeParameters(
diff --git a/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
index dbc8523..7b79cea 100644
--- a/content/renderer/browser_plugin/browser_plugin_browsertest.cc
+++ b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
@@ -167,8 +167,8 @@ TEST_F(BrowserPluginTest, InitialResize) {
ASSERT_TRUE(msg);
BrowserPluginHostMsg_Attach_Params params;
BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
- EXPECT_EQ(640, params.resize_guest_params.view_size.width());
- EXPECT_EQ(480, params.resize_guest_params.view_size.height());
+ EXPECT_EQ(640, params.resize_guest_params.view_rect.width());
+ EXPECT_EQ(480, params.resize_guest_params.view_rect.height());
}
MockBrowserPlugin* browser_plugin =
@@ -320,18 +320,25 @@ TEST_F(BrowserPluginTest, ResizeFlowControl) {
ExecuteJavaScript("document.getElementById('browserplugin').width = '643px'");
ProcessPendingMessages();
- // Expect to see one messsage in the sink. BrowserPlugin will not issue
+ // Expect to see one resize messsage in the sink. BrowserPlugin will not issue
// subsequent resize requests until the first request is satisfied by the
- // guest.
- EXPECT_EQ(1u, browser_plugin_manager()->sink().message_count());
+ // guest. The rest of the messages could be
+ // BrowserPluginHostMsg_UpdateGeometry msgs.
+ EXPECT_LE(1u, browser_plugin_manager()->sink().message_count());
+ for (size_t i = 0; i < browser_plugin_manager()->sink().message_count();
+ ++i) {
+ const IPC::Message* msg = browser_plugin_manager()->sink().GetMessageAt(i);
+ if (msg->type() != BrowserPluginHostMsg_ResizeGuest::ID)
+ EXPECT_EQ(msg->type(), BrowserPluginHostMsg_UpdateGeometry::ID);
+ }
const IPC::Message* msg =
- browser_plugin_manager()->sink().GetFirstMessageMatching(
+ browser_plugin_manager()->sink().GetUniqueMessageMatching(
BrowserPluginHostMsg_ResizeGuest::ID);
ASSERT_TRUE(msg);
BrowserPluginHostMsg_ResizeGuest_Params params;
BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, &params);
- EXPECT_EQ(641, params.view_size.width());
- EXPECT_EQ(480, params.view_size.height());
+ EXPECT_EQ(641, params.view_rect.width());
+ EXPECT_EQ(480, params.view_rect.height());
// This indicates that the BrowserPlugin has sent out a previous resize
// request but has not yet received an UpdateRect for that request.
EXPECT_TRUE(browser_plugin->pending_damage_buffer_.get());