// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/command_line.h"
#include "base/memory/singleton.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "base/utf_string_conversions.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
#include "content/browser/browser_plugin/test_browser_plugin_embedder.h"
#include "content/browser/browser_plugin/test_browser_plugin_guest.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/view_messages.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/shell.h"
#include "content/test/content_browser_test_utils.h"
#include "content/test/content_browser_test.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "webkit/glue/webdropdata.h"
using WebKit::WebInputEvent;
using WebKit::WebMouseEvent;
using content::BrowserPluginEmbedder;
using content::BrowserPluginGuest;
using content::BrowserPluginHostFactory;
using content::WebContentsImpl;
namespace {
const char kHTMLForGuest[] =
"data:text/html,
hello world";
const char kHTMLForGuestBusyLoop[] =
"data:text/html,";
const char kHTMLForGuestTouchHandler[] =
"data:text/html,With touch
"
"";
const char kHTMLForGuestWithTitle[] =
"data:text/html,"
"%s"
"hello world"
"";
const char kHTMLForGuestAcceptDrag[] =
"data:text/html,"
""
""
"";
const char kHTMLForGuestWithSize[] =
"data:text/html,"
""
""
"
"
""
"";
std::string GetHTMLForGuestWithTitle(const std::string& title) {
return StringPrintf(kHTMLForGuestWithTitle, title.c_str());
}
} // namespace
namespace content {
// Test factory for creating test instances of BrowserPluginEmbedder and
// BrowserPluginGuest.
class TestBrowserPluginHostFactory : public BrowserPluginHostFactory {
public:
virtual BrowserPluginGuest* CreateBrowserPluginGuest(
int instance_id,
WebContentsImpl* web_contents,
const BrowserPluginHostMsg_CreateGuest_Params& params) OVERRIDE {
return new TestBrowserPluginGuest(instance_id,
web_contents,
params);
}
// Also keeps track of number of instances created.
virtual BrowserPluginEmbedder* CreateBrowserPluginEmbedder(
WebContentsImpl* web_contents,
RenderViewHost* render_view_host) OVERRIDE {
embedder_instance_count_++;
if (message_loop_runner_)
message_loop_runner_->Quit();
return new TestBrowserPluginEmbedder(web_contents, render_view_host);
}
// Singleton getter.
static TestBrowserPluginHostFactory* GetInstance() {
return Singleton::get();
}
// Waits for at least one embedder to be created in the test. Returns true if
// we have a guest, false if waiting times out.
void WaitForEmbedderCreation() {
// Check if already have created instance.
if (embedder_instance_count_ > 0)
return;
// Wait otherwise.
message_loop_runner_ = new MessageLoopRunner();
message_loop_runner_->Run();
}
protected:
TestBrowserPluginHostFactory() : embedder_instance_count_(0) {}
virtual ~TestBrowserPluginHostFactory() {}
private:
// For Singleton.
friend struct DefaultSingletonTraits;
scoped_refptr message_loop_runner_;
int embedder_instance_count_;
DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginHostFactory);
};
// Test factory class for browser plugin that creates guests with short hang
// timeout.
class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory {
public:
virtual BrowserPluginGuest* CreateBrowserPluginGuest(
int instance_id,
WebContentsImpl* web_contents,
const BrowserPluginHostMsg_CreateGuest_Params& params) OVERRIDE {
BrowserPluginGuest* guest =
new TestBrowserPluginGuest(instance_id,
web_contents,
params);
guest->set_guest_hang_timeout_for_testing(TestTimeouts::tiny_timeout());
return guest;
}
// Singleton getter.
static TestShortHangTimeoutGuestFactory* GetInstance() {
return Singleton::get();
}
protected:
TestShortHangTimeoutGuestFactory() {}
virtual ~TestShortHangTimeoutGuestFactory() {}
private:
// For Singleton.
friend struct DefaultSingletonTraits;
DISALLOW_COPY_AND_ASSIGN(TestShortHangTimeoutGuestFactory);
};
// A transparent observer that can be used to verify that a RenderViewHost
// received a specific message.
class RenderViewHostMessageObserver : public RenderViewHostObserver {
public:
RenderViewHostMessageObserver(RenderViewHost* host,
uint32 message_id)
: RenderViewHostObserver(host),
message_id_(message_id),
message_received_(false) {
}
virtual ~RenderViewHostMessageObserver() {}
void WaitUntilMessageReceived() {
if (message_received_)
return;
message_loop_runner_ = new MessageLoopRunner();
message_loop_runner_->Run();
}
void ResetState() {
message_received_ = false;
}
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
if (message.type() == message_id_) {
message_received_ = true;
if (message_loop_runner_)
message_loop_runner_->Quit();
}
return false;
}
private:
scoped_refptr message_loop_runner_;
uint32 message_id_;
bool message_received_;
DISALLOW_COPY_AND_ASSIGN(RenderViewHostMessageObserver);
};
class BrowserPluginHostTest : public ContentBrowserTest {
public:
BrowserPluginHostTest()
: test_embedder_(NULL),
test_guest_(NULL) {}
virtual void SetUp() OVERRIDE {
// Override factory to create tests instances of BrowserPlugin*.
content::BrowserPluginEmbedder::set_factory_for_testing(
TestBrowserPluginHostFactory::GetInstance());
content::BrowserPluginGuest::set_factory_for_testing(
TestBrowserPluginHostFactory::GetInstance());
ContentBrowserTest::SetUp();
}
virtual void TearDown() OVERRIDE {
content::BrowserPluginEmbedder::set_factory_for_testing(NULL);
content::BrowserPluginGuest::set_factory_for_testing(NULL);
ContentBrowserTest::TearDown();
}
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
// Enable browser plugin in content_shell for running test.
command_line->AppendSwitch(switches::kEnableBrowserPluginForAllViewTypes);
}
static void SimulateSpaceKeyPress(WebContents* web_contents) {
SimulateKeyPress(web_contents,
ui::VKEY_SPACE,
false, // control.
false, // shift.
false, // alt.
false); // command.
}
static void SimulateTabKeyPress(WebContents* web_contents) {
SimulateKeyPress(web_contents,
ui::VKEY_TAB,
false, // control.
false, // shift.
false, // alt.
false); // command.
}
// Executes the javascript synchronously and makes sure the returned value is
// freed properly.
void ExecuteSyncJSFunction(RenderViewHost* rvh, const string16& jscript) {
scoped_ptr value(rvh->ExecuteJavascriptAndGetValue(
string16(), jscript));
}
// This helper method does the following:
// 1. Start the test server and navigate the shell to |embedder_url|.
// 2. Execute custom pre-navigation |embedder_code| if provided.
// 3. Navigate the guest to the |guest_url|.
// 4. Verify that the guest has been created and has completed loading.
void StartBrowserPluginTest(const std::string& embedder_url,
const std::string& guest_url,
bool is_guest_data_url,
const std::string& embedder_code) {
ASSERT_TRUE(test_server()->Start());
GURL test_url(test_server()->GetURL(embedder_url));
NavigateToURL(shell(), test_url);
WebContentsImpl* embedder_web_contents = static_cast(
shell()->web_contents());
RenderViewHostImpl* rvh = static_cast(
embedder_web_contents->GetRenderViewHost());
// Focus the embedder.
rvh->Focus();
// Allow the test to do some operations on the embedder before we perform
// the first navigation of the guest.
if (!embedder_code.empty())
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(embedder_code));
if (!is_guest_data_url) {
test_url = test_server()->GetURL(guest_url);
ExecuteSyncJSFunction(rvh,
ASCIIToUTF16(StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
} else {
ExecuteSyncJSFunction(rvh,
ASCIIToUTF16(StringPrintf("SetSrc('%s');", guest_url.c_str())));
}
// Wait to make sure embedder is created/attached to WebContents.
TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation();
test_embedder_ = static_cast(
embedder_web_contents->GetBrowserPluginEmbedder());
ASSERT_TRUE(test_embedder_);
test_embedder_->WaitForGuestAdded();
// Verify that we have exactly one guest.
const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
test_embedder_->guest_web_contents_for_testing();
EXPECT_EQ(1u, instance_map.size());
WebContentsImpl* test_guest_web_contents = static_cast(
instance_map.begin()->second);
test_guest_ = static_cast(
test_guest_web_contents->GetBrowserPluginGuest());
test_guest_->WaitForLoadStop();
}
TestBrowserPluginEmbedder* test_embedder() const { return test_embedder_; }
TestBrowserPluginGuest* test_guest() const { return test_guest_; }
private:
TestBrowserPluginEmbedder* test_embedder_;
TestBrowserPluginGuest* test_guest_;
DISALLOW_COPY_AND_ASSIGN(BrowserPluginHostTest);
};
// This test loads a guest that has a busy loop, and therefore it hangs the
// guest.
//
// Disabled on Windows and Linux since it is flaky. crbug.com/164812
#if defined(OS_WIN) || defined(OS_LINUX)
#define MAYBE_GuestUnresponsive DISABLED_GuestUnresponsive
#else
#define MAYBE_GuestUnresponsive GuestUnresponsive
#endif
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest,
MAYBE_GuestUnresponsive) {
// Override the hang timeout for guest to be very small.
content::BrowserPluginGuest::set_factory_for_testing(
TestShortHangTimeoutGuestFactory::GetInstance());
const char kEmbedderURL[] =
"files/browser_plugin_embedder_guest_unresponsive.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuestBusyLoop, true, "");
// Wait until the busy loop starts.
{
const string16 expected_title = ASCIIToUTF16("start");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
// Hang the guest for a length of time.
int spin_time = 10 * TestTimeouts::tiny_timeout().InMilliseconds();
ExecuteSyncJSFunction(test_guest()->web_contents()->GetRenderViewHost(),
ASCIIToUTF16(StringPrintf("StartPauseMs(%d);", spin_time).c_str()));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
{
const string16 expected_title = ASCIIToUTF16("done");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
// Send a mouse event to the guest.
SimulateMouseClick(test_embedder()->web_contents(), 0,
WebKit::WebMouseEvent::ButtonLeft);
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// Verify that the embedder has received the 'unresponsive' and 'responsive'
// events.
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
scoped_ptr value(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("unresponsiveCalled")));
bool result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
value.reset(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("responsiveCalled")));
result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
}
// This test ensures that if guest isn't there and we resize the guest (from
// js), it remembers the size correctly.
//
// Initially we load an embedder with a guest without a src attribute (which has
// dimension 640x480), resize it to 100x200, and then we set the source to a
// sample guest. In the end we verify that the correct size has been set.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, NavigateAfterResize) {
const gfx::Size nxt_size = gfx::Size(100, 200);
const std::string embedder_code =
StringPrintf("SetSize(%d, %d);", nxt_size.width(), nxt_size.height());
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, embedder_code);
// Wait for the guest to receive a damage buffer of size 100x200.
// This means the guest will be painted properly at that size.
test_guest()->WaitForDamageBufferWithSize(nxt_size);
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AdvanceFocus) {
const char kEmbedderURL[] = "files/browser_plugin_focus.html";
const char* kGuestURL = "files/browser_plugin_focus_child.html";
StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, "");
SimulateMouseClick(test_embedder()->web_contents(), 0,
WebKit::WebMouseEvent::ButtonLeft);
BrowserPluginHostTest::SimulateTabKeyPress(test_embedder()->web_contents());
// Wait until we focus into the guest.
test_guest()->WaitForFocus();
// TODO(fsamuel): A third Tab key press should not be necessary.
// The browser plugin will take keyboard focus but it will not
// focus an initial element. The initial element is dependent
// upon tab direction which WebKit does not propagate to the plugin.
// See http://crbug.com/147644.
BrowserPluginHostTest::SimulateTabKeyPress(test_embedder()->web_contents());
BrowserPluginHostTest::SimulateTabKeyPress(test_embedder()->web_contents());
BrowserPluginHostTest::SimulateTabKeyPress(test_embedder()->web_contents());
test_guest()->WaitForAdvanceFocus();
}
// This test opens a page in http and then opens another page in https, forcing
// a RenderViewHost swap in the web_contents. We verify that the embedder in the
// web_contents gets cleared properly.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) {
net::TestServer https_server(
net::TestServer::TYPE_HTTPS,
net::TestServer::kLocalhost,
FilePath(FILE_PATH_LITERAL("content/test/data")));
ASSERT_TRUE(https_server.Start());
// 1. Load an embedder page with one guest in it.
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
// 2. Navigate to a URL in https, so we trigger a RenderViewHost swap.
GURL test_https_url(https_server.GetURL(
"files/browser_plugin_title_change.html"));
content::WindowedNotificationObserver swap_observer(
content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
content::Source(test_embedder()->web_contents()));
NavigateToURL(shell(), test_https_url);
swap_observer.Wait();
TestBrowserPluginEmbedder* test_embedder_after_swap =
static_cast(
static_cast(shell()->web_contents())->
GetBrowserPluginEmbedder());
// Verify we have a no embedder in web_contents (since the new page doesn't
// have any browser plugin).
ASSERT_TRUE(!test_embedder_after_swap);
ASSERT_NE(test_embedder(), test_embedder_after_swap);
}
// This test opens two pages in http and there is no RenderViewHost swap,
// therefore the embedder created on first page navigation stays the same in
// web_contents.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
WebContentsImpl* embedder_web_contents = test_embedder()->web_contents();
// Navigate to another page in same host and port, so RenderViewHost swap
// does not happen and existing embedder doesn't change in web_contents.
GURL test_url_new(test_server()->GetURL(
"files/browser_plugin_title_change.html"));
const string16 expected_title = ASCIIToUTF16("done");
content::TitleWatcher title_watcher(shell()->web_contents(), expected_title);
NavigateToURL(shell(), test_url_new);
LOG(INFO) << "Start waiting for title";
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
LOG(INFO) << "Done navigating to second page";
TestBrowserPluginEmbedder* test_embedder_after_nav =
static_cast(
embedder_web_contents->GetBrowserPluginEmbedder());
// Embedder must not change in web_contents.
ASSERT_EQ(test_embedder_after_nav, test_embedder());
}
// This test verifies that hiding the embedder also hides the guest.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, BrowserPluginVisibilityChanged) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
// Hide the Browser Plugin.
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').style.visibility = 'hidden'"));
// Make sure that the guest is hidden.
test_guest()->WaitUntilHidden();
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderVisibilityChanged) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
// Hide the embedder.
test_embedder()->web_contents()->WasHidden();
// Make sure that hiding the embedder also hides the guest.
test_guest()->WaitUntilHidden();
}
// This test verifies that calling the reload method reloads the guest.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadGuest) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
test_guest()->ResetUpdateRectCount();
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').reload()"));
test_guest()->WaitForReload();
}
// This test verifies that calling the stop method forwards the stop request
// to the guest's WebContents.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, StopGuest) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').stop()"));
test_guest()->WaitForStop();
}
// Verifies that installing/uninstalling touch-event handlers in the guest
// plugin correctly updates the touch-event handling state in the embedder.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AcceptTouchEvents) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuestTouchHandler, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
// The embedder should not have any touch event handlers at this point.
EXPECT_FALSE(rvh->has_touch_handler());
// Install the touch handler in the guest. This should cause the embedder to
// start listening for touch events too.
RenderViewHostMessageObserver observer(rvh,
ViewHostMsg_HasTouchEventHandlers::ID);
ExecuteSyncJSFunction(test_guest()->web_contents()->GetRenderViewHost(),
ASCIIToUTF16("InstallTouchHandler();"));
observer.WaitUntilMessageReceived();
EXPECT_TRUE(rvh->has_touch_handler());
// Uninstalling the touch-handler in guest should cause the embedder to stop
// listening for touch events.
observer.ResetState();
ExecuteSyncJSFunction(test_guest()->web_contents()->GetRenderViewHost(),
ASCIIToUTF16("UninstallTouchHandler();"));
observer.WaitUntilMessageReceived();
EXPECT_FALSE(rvh->has_touch_handler());
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, Renavigate) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(
kEmbedderURL, GetHTMLForGuestWithTitle("P1"), true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
// Navigate to P2 and verify that the navigation occurred.
{
const string16 expected_title = ASCIIToUTF16("P2");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(StringPrintf("SetSrc('%s');",
GetHTMLForGuestWithTitle("P2").c_str())));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// Navigate to P3 and verify that the navigation occurred.
{
const string16 expected_title = ASCIIToUTF16("P3");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(StringPrintf("SetSrc('%s');",
GetHTMLForGuestWithTitle("P3").c_str())));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// Go back and verify that we're back at P2.
{
const string16 expected_title = ASCIIToUTF16("P2");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16("Back();"));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
scoped_ptr value(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("CanGoBack()")));
bool result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
value.reset(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("CanGoForward()")));
result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
}
// Go forward and verify that we're back at P3.
{
const string16 expected_title = ASCIIToUTF16("P3");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16("Forward();"));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
scoped_ptr value(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("CanGoForward()")));
bool result = true;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_FALSE(result);
}
// Go back two entries and verify that we're back at P1.
{
const string16 expected_title = ASCIIToUTF16("P1");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16("Go(-2);"));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
scoped_ptr value(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("CanGoBack()")));
bool result = true;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_FALSE(result);
}
}
// This tests verifies that reloading the embedder does not crash the browser
// and that the guest is reset.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
// Change the title of the page to 'modified' so that we know that
// the page has successfully reloaded when it goes back to 'embedder'
// in the next step.
{
const string16 expected_title = ASCIIToUTF16("modified");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(StringPrintf("SetTitle('%s');",
"modified")));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// Reload the embedder page, and verify that the reload was successful.
// Then navigate the guest to verify that the browser process does not crash.
{
const string16 expected_title = ASCIIToUTF16("embedder");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
test_embedder()->web_contents()->GetController().Reload(false);
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
ExecuteSyncJSFunction(test_embedder()->web_contents()->GetRenderViewHost(),
ASCIIToUTF16(StringPrintf("SetSrc('%s');", kHTMLForGuest)));
const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
test_embedder()->guest_web_contents_for_testing();
WebContentsImpl* test_guest_web_contents = static_cast(
instance_map.begin()->second);
TestBrowserPluginGuest* new_test_guest =
static_cast(
test_guest_web_contents->GetBrowserPluginGuest());
// Wait for the guest to send an UpdateRectMsg, meaning it is ready.
new_test_guest->WaitForUpdateRectMsg();
}
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, TerminateGuest) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').terminate()"));
// Expect the guest to crash.
test_guest()->WaitForExit();
}
// This test verifies that the guest is responsive after crashing and going back
// to a previous navigation entry.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, BackAfterTerminateGuest) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(
kEmbedderURL, GetHTMLForGuestWithTitle("P1"), true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
// Navigate to P2 and verify that the navigation occurred.
{
const string16 expected_title = ASCIIToUTF16("P2");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(StringPrintf("SetSrc('%s');",
GetHTMLForGuestWithTitle("P2").c_str())));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// Kill the guest.
ExecuteSyncJSFunction(rvh,
ASCIIToUTF16("document.getElementById('plugin').terminate()"));
// Expect the guest to report that it crashed.
test_guest()->WaitForExit();
// Go back and verify that we're back at P1.
{
const string16 expected_title = ASCIIToUTF16("P1");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16("Back();"));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// Send an input event and verify that the guest receives the input.
SimulateMouseClick(test_embedder()->web_contents(), 0,
WebKit::WebMouseEvent::ButtonLeft);
test_guest()->WaitForInput();
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadStart) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
const string16 expected_title = ASCIIToUTF16(kHTMLForGuest);
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
// Renavigate the guest to |kHTMLForGuest|.
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
StringPrintf("SetSrc('%s');", kHTMLForGuest)));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadAbort) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
{
// Navigate the guest to "close-socket".
const string16 expected_title = ASCIIToUTF16("ERR_EMPTY_RESPONSE");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
GURL test_url = test_server()->GetURL("close-socket");
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
{
// Navigate the guest to an illegal chrome:// URL.
const string16 expected_title = ASCIIToUTF16("ERR_FAILED");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
GURL test_url("chrome://newtab");
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
{
// Navigate the guest to an illegal file:// URL.
const string16 expected_title = ASCIIToUTF16("ERR_ABORTED");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
GURL test_url("file://foo");
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadRedirect) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
const string16 expected_title = ASCIIToUTF16("redirected");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
// Navigate with a redirect and wait until the title changes.
GURL redirect_url(test_server()->GetURL(
"server-redirect?files/title1.html"));
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
StringPrintf("SetSrc('%s');", redirect_url.spec().c_str())));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
// Verify that we heard a loadRedirect during the navigation.
scoped_ptr value(rvh->ExecuteJavascriptAndGetValue(
string16(), ASCIIToUTF16("redirectOldUrl")));
std::string result;
EXPECT_TRUE(value->GetAsString(&result));
EXPECT_EQ(redirect_url.spec().c_str(), result);
value.reset(rvh->ExecuteJavascriptAndGetValue(
string16(), ASCIIToUTF16("redirectNewUrl")));
EXPECT_TRUE(value->GetAsString(&result));
EXPECT_EQ(test_server()->GetURL("files/title1.html").spec().c_str(), result);
}
// Tests that a drag-n-drop over the browser plugin in the embedder happens
// correctly.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AcceptDragEvents) {
const char kEmbedderURL[] = "files/browser_plugin_dragging.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuestAcceptDrag, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
// Get a location in the embedder outside of the plugin.
base::ListValue *start, *end;
scoped_ptr value(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("dragLocation()")));
ASSERT_TRUE(value->GetAsList(&start) && start->GetSize() == 2);
double start_x, start_y;
ASSERT_TRUE(start->GetDouble(0, &start_x) && start->GetDouble(1, &start_y));
// Get a location in the embedder that falls inside the plugin.
value.reset(rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("dropLocation()")));
ASSERT_TRUE(value->GetAsList(&end) && end->GetSize() == 2);
double end_x, end_y;
ASSERT_TRUE(end->GetDouble(0, &end_x) && end->GetDouble(1, &end_y));
WebDropData drop_data;
GURL url = GURL("https://www.domain.com/index.html");
drop_data.url = url;
// Pretend that the URL is being dragged over the embedder. Start the drag
// from outside the plugin, then move the drag inside the plugin and drop.
// This should trigger appropriate messages from the embedder to the guest,
// and end with a drop on the guest. The guest changes title when a drop
// happens.
const string16 expected_title = ASCIIToUTF16("DROPPED");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
rvh->DragTargetDragEnter(drop_data, gfx::Point(start_x, start_y),
gfx::Point(start_x, start_y), WebKit::WebDragOperationEvery, 0);
rvh->DragTargetDragOver(gfx::Point(end_x, end_y), gfx::Point(end_x, end_y),
WebKit::WebDragOperationEvery, 0);
rvh->DragTargetDrop(gfx::Point(end_x, end_y), gfx::Point(end_x, end_y), 0);
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// This test verifies that round trip postMessage works as expected.
// 1. The embedder posts a message 'testing123' to the guest.
// 2. The guest receives and replies to the message using the event object's
// source object: event.source.postMessage('foobar', '*')
// 3. The embedder receives the message and uses the event's source
// object to do one final reply: 'stop'
// 4. The guest receives the final 'stop' message.
// 5. The guest acks the 'stop' message with a 'stop_ack' message.
// 6. The embedder changes its title to 'main guest' when it sees the 'stop_ack'
// message.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PostMessage) {
const char* kTesting = "testing123";
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
const char* kGuestURL = "files/browser_plugin_post_message_guest.html";
StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
{
const string16 expected_title = ASCIIToUTF16("main guest");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
// By the time we get here 'contentWindow' should be ready because the
// guest has completed loading.
ExecuteSyncJSFunction(rvh,
ASCIIToUTF16(StringPrintf("PostMessage('%s, false');", kTesting)));
// The title will be updated to "main guest" at the last stage of the
// process described above.
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
}
// This is the same as BrowserPluginHostTest.PostMessage but also
// posts a message to an iframe.
// TODO(fsamuel): This test should replace the previous test once postMessage
// iframe targeting is fixed (see http://crbug.com/153701).
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) {
const char* kTesting = "testing123";
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
const char* kGuestURL = "files/browser_plugin_post_message_guest.html";
StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
{
const string16 expected_title = ASCIIToUTF16("main guest");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh,
ASCIIToUTF16(StringPrintf("PostMessage('%s, false');", kTesting)));
// The title will be updated to "main guest" at the last stage of the
// process described above.
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
{
content::TitleWatcher ready_watcher(test_embedder()->web_contents(),
ASCIIToUTF16("ready"));
RenderViewHostImpl* guest_rvh = static_cast(
test_guest()->web_contents()->GetRenderViewHost());
GURL test_url = test_server()->GetURL(
"files/browser_plugin_post_message_guest.html");
ExecuteSyncJSFunction(guest_rvh,
ASCIIToUTF16(StringPrintf("CreateChildFrame('%s');",
test_url.spec().c_str())));
string16 actual_title = ready_watcher.WaitAndGetTitle();
EXPECT_EQ(ASCIIToUTF16("ready"), actual_title);
content::TitleWatcher iframe_watcher(test_embedder()->web_contents(),
ASCIIToUTF16("iframe"));
ExecuteSyncJSFunction(rvh,
ASCIIToUTF16(StringPrintf("PostMessage('%s', true);", kTesting)));
// The title will be updated to "iframe" at the last stage of the
// process described above.
actual_title = iframe_watcher.WaitAndGetTitle();
EXPECT_EQ(ASCIIToUTF16("iframe"), actual_title);
}
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadStop) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
const string16 expected_title = ASCIIToUTF16("loadStop");
content::TitleWatcher title_watcher(
test_embedder()->web_contents(), expected_title);
// Renavigate the guest to |kHTMLForGuest|.
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
StringPrintf("SetSrc('%s');", kHTMLForGuest)));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadCommit) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
const string16 expected_title = ASCIIToUTF16(
StringPrintf("loadCommit:%s", kHTMLForGuest));
content::TitleWatcher title_watcher(
test_embedder()->web_contents(), expected_title);
// Renavigate the guest to |kHTMLForGuest|.
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
StringPrintf("SetSrc('%s');", kHTMLForGuest)));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
scoped_ptr is_top_level(rvh->ExecuteJavascriptAndGetValue(
string16(), ASCIIToUTF16("commitIsTopLevel")));
bool top_level_bool = false;
EXPECT_TRUE(is_top_level->GetAsBoolean(&top_level_bool));
EXPECT_EQ(true, top_level_bool);
}
// This test verifies that if a browser plugin is hidden before navigation,
// the guest starts off hidden.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, HiddenBeforeNavigation) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
const std::string embedder_code =
"document.getElementById('plugin').style.visibility = 'hidden'";
StartBrowserPluginTest(
kEmbedderURL, kHTMLForGuest, true, embedder_code);
EXPECT_FALSE(test_guest()->visible());
}
// This test verifies that if we lose the guest, and get a new one,
// the new guest will inherit the visibility state of the old guest.
//
// Very flaky on Linux, Linux CrOS, somewhat flaky on XP, slightly on
// Mac; http://crbug.com/162809.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_VisibilityPreservation) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
// Hide the BrowserPlugin.
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').style.visibility = 'hidden';"));
test_guest()->WaitUntilHidden();
// Kill the current guest.
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').terminate();"));
test_guest()->WaitForExit();
// Get a new guest.
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').reload();"));
test_guest()->WaitForLoadStop();
// Verify that the guest is told to hide.
test_guest()->WaitUntilHidden();
}
// This test verifies that if a browser plugin is focused before navigation then
// the guest starts off focused.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, FocusBeforeNavigation) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
const std::string embedder_code =
"document.getElementById('plugin').focus();";
StartBrowserPluginTest(
kEmbedderURL, kHTMLForGuest, true, embedder_code);
RenderViewHostImpl* guest_rvh = static_cast(
test_guest()->web_contents()->GetRenderViewHost());
// Verify that the guest is focused.
scoped_ptr value(
guest_rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("document.hasFocus()")));
bool result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
}
// This test verifies that if we lose the guest, and get a new one,
// the new guest will inherit the focus state of the old guest.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, FocusPreservation) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
RenderViewHostImpl* guest_rvh = static_cast(
test_guest()->web_contents()->GetRenderViewHost());
{
// Focus the BrowserPlugin. This will have the effect of also focusing the
// current guest.
ExecuteSyncJSFunction(
rvh, ASCIIToUTF16("document.getElementById('plugin').focus();"));
// Verify that key presses go to the guest.
SimulateSpaceKeyPress(test_embedder()->web_contents());
test_guest()->WaitForInput();
// Verify that the guest is focused.
scoped_ptr value(
guest_rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("document.hasFocus()")));
bool result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
}
// Kill the current guest.
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').terminate();"));
test_guest()->WaitForExit();
{
// Get a new guest.
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').reload();"));
test_guest()->WaitForLoadStop();
// Verify that the guest is focused.
scoped_ptr value(
guest_rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("document.hasFocus()")));
bool result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
}
}
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, FocusTracksEmbedder) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
RenderViewHostImpl* guest_rvh = static_cast(
test_guest()->web_contents()->GetRenderViewHost());
{
// Focus the BrowserPlugin. This will have the effect of also focusing the
// current guest.
ExecuteSyncJSFunction(
rvh, ASCIIToUTF16("document.getElementById('plugin').focus();"));
// Verify that key presses go to the guest.
SimulateSpaceKeyPress(test_embedder()->web_contents());
test_guest()->WaitForInput();
// Verify that the guest is focused.
scoped_ptr value(
guest_rvh->ExecuteJavascriptAndGetValue(string16(),
ASCIIToUTF16("document.hasFocus()")));
bool result = false;
ASSERT_TRUE(value->GetAsBoolean(&result));
EXPECT_TRUE(result);
}
// Blur the embedder.
test_embedder()->web_contents()->GetRenderViewHost()->Blur();
test_guest()->WaitForBlur();
}
// This test verifies that if a browser plugin is in autosize mode before
// navigation then the guest starts auto-sized.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AutoSizeBeforeNavigation) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
const std::string embedder_code =
"document.getElementById('plugin').minWidth = 300;"
"document.getElementById('plugin').minHeight = 200;"
"document.getElementById('plugin').maxWidth = 600;"
"document.getElementById('plugin').maxHeight = 400;"
"document.getElementById('plugin').autoSize = true;";
StartBrowserPluginTest(
kEmbedderURL, kHTMLForGuestWithSize, true, embedder_code);
// Verify that the guest has been auto-sized.
test_guest()->WaitForViewSize(gfx::Size(300, 400));
}
// This test verifies that enabling autosize resizes the guest and triggers
// a 'sizechanged' event.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AutoSizeAfterNavigation) {
const char* kEmbedderURL = "files/browser_plugin_embedder.html";
StartBrowserPluginTest(
kEmbedderURL, kHTMLForGuestWithSize, true, "");
RenderViewHostImpl* rvh = static_cast(
test_embedder()->web_contents()->GetRenderViewHost());
{
const string16 expected_title = ASCIIToUTF16("AutoSize(300, 400)");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').minWidth = 300;"
"document.getElementById('plugin').minHeight = 200;"
"document.getElementById('plugin').maxWidth = 600;"
"document.getElementById('plugin').maxHeight = 400;"
"document.getElementById('plugin').autoSize = true;"));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
{
// Change the minWidth and verify that it causes relayout.
const string16 expected_title = ASCIIToUTF16("AutoSize(350, 400)");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').minWidth = 350;"));
string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
{
// Turn off autoSize and verify that the guest resizes to fit the container.
ExecuteSyncJSFunction(rvh, ASCIIToUTF16(
"document.getElementById('plugin').autoSize = false;"));
test_guest()->WaitForViewSize(gfx::Size(640, 480));
}
}
// Test for regression http://crbug.com/162961.
IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, GetRenderViewHostAtPositionTest) {
const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
const std::string embedder_code = StringPrintf("SetSize(%d, %d);", 100, 100);
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuestWithSize, true,
embedder_code);
// Check for render view host at position (150, 150) that is outside the
// bounds of our guest, so this would respond with the render view host of the
// embedder.
test_embedder()->WaitForRenderViewHostAtPosition(150, 150);
ASSERT_EQ(test_embedder()->web_contents()->GetRenderViewHost(),
test_embedder()->last_rvh_at_position_response());
}
} // namespace content