Skip to content

Commit

Permalink
<webview>: Implement CopyFromCompositingSurface() for guests in <webv…
Browse files Browse the repository at this point in the history
…iew>

BUG=326756
R=alexst@chromium.org, fsamuel@chromium.org, kenrb@chromium.org

Review URL: https://codereview.chromium.org/99143004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240020 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
sadrul@chromium.org committed Dec 11, 2013
1 parent 78f9d8b commit 73405fb
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 8 deletions.
24 changes: 19 additions & 5 deletions chrome/browser/apps/web_view_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1846,17 +1846,31 @@ IN_PROC_BROWSER_TEST_F(WebViewPluginTest, TestLoadPluginEvent) {

// Taking a screenshot does not work with threaded compositing, so disable
// threaded compositing for this test (http://crbug.com/326756).
class WebViewWithoutThreadedCompositingTest : public WebViewTest {
class WebViewCaptureTest : public WebViewTest,
public testing::WithParamInterface<std::string> {
public:
WebViewWithoutThreadedCompositingTest() {}
virtual ~WebViewWithoutThreadedCompositingTest() {}
WebViewCaptureTest() {}
virtual ~WebViewCaptureTest() {}
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(switches::kDisableThreadedCompositing);
command_line->AppendSwitch(GetParam());
// http://crbug.com/327035
command_line->AppendSwitch(switches::kDisableDelegatedRenderer);
WebViewTest::SetUpCommandLine(command_line);
}
};

IN_PROC_BROWSER_TEST_F(WebViewWithoutThreadedCompositingTest,
IN_PROC_BROWSER_TEST_P(WebViewCaptureTest,
Shim_ScreenshotCapture) {
TestHelper("testScreenshotCapture", "web_view/shim", NO_TEST_SERVER);
}

INSTANTIATE_TEST_CASE_P(WithoutThreadedCompositor,
WebViewCaptureTest,
::testing::Values(std::string(switches::kDisableThreadedCompositing)));

// http://crbug.com/171744
#if !defined(OS_MACOSX)
INSTANTIATE_TEST_CASE_P(WithThreadedCompositor,
WebViewCaptureTest,
::testing::Values(std::string(switches::kEnableThreadedCompositing)));
#endif
26 changes: 26 additions & 0 deletions content/browser/browser_plugin/browser_plugin_guest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ BrowserPluginGuest::BrowserPluginGuest(
mouse_locked_(false),
pending_lock_request_(false),
embedder_visible_(true),
copy_request_id_(0),
next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
has_render_view_(has_render_view),
last_seen_auto_size_enabled_(false),
Expand Down Expand Up @@ -507,6 +508,8 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
OnSwapBuffersACK)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK,
OnCompositorFrameACK)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
OnCopyFromCompositingSurfaceAck)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
OnDragStatusUpdate)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
Expand Down Expand Up @@ -686,6 +689,16 @@ void BrowserPluginGuest::UpdateVisibility() {
OnSetVisibility(instance_id_, visible());
}

void BrowserPluginGuest::CopyFromCompositingSurface(
gfx::Rect src_subrect,
gfx::Size dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback) {
copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
SendMessageToEmbedder(
new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
copy_request_id_, src_subrect, dst_size));
}

// screen.
gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
gfx::Rect guest_rect(bounds);
Expand Down Expand Up @@ -1121,6 +1134,7 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
switch (message.type()) {
case BrowserPluginHostMsg_BuffersSwappedACK::ID:
case BrowserPluginHostMsg_CompositorFrameACK::ID:
case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
case BrowserPluginHostMsg_DragStatusUpdate::ID:
case BrowserPluginHostMsg_ExecuteEditCommand::ID:
case BrowserPluginHostMsg_HandleInputEvent::ID:
Expand Down Expand Up @@ -1564,6 +1578,18 @@ void BrowserPluginGuest::OnUpdateRectACK(
OnSetSize(instance_id_, auto_size_params, resize_guest_params);
}

void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
int instance_id,
int request_id,
const SkBitmap& bitmap) {
CHECK(copy_request_callbacks_.count(request_id));
if (!copy_request_callbacks_.count(request_id))
return;
const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
copy_request_callbacks_.erase(request_id);
}

void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
const gfx::Rect& view_rect) {
// The plugin has moved within the embedder without resizing or the
Expand Down
16 changes: 15 additions & 1 deletion content/browser/browser_plugin/browser_plugin_guest.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ class CONTENT_EXPORT BrowserPluginGuest

void UpdateVisibility();

void CopyFromCompositingSurface(
gfx::Rect src_subrect,
gfx::Size dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback);

// WebContentsObserver implementation.
virtual void DidCommitProvisionalLoadForFrame(
int64 frame_id,
Expand Down Expand Up @@ -375,7 +380,9 @@ class CONTENT_EXPORT BrowserPluginGuest
uint32 output_surface_id,
int renderer_host_id,
const cc::CompositorFrameAck& ack);

void OnCopyFromCompositingSurfaceAck(int instance_id,
int request_id,
const SkBitmap& bitmap);
// Handles drag events from the embedder.
// When dragging, the drag events go to the embedder first, and if the drag
// happens on the browser plugin, then the plugin sends a corresponding
Expand Down Expand Up @@ -528,6 +535,13 @@ class CONTENT_EXPORT BrowserPluginGuest
gfx::Size max_auto_size_;
gfx::Size min_auto_size_;

// Each copy-request is identified by a unique number. The unique number is
// used to keep track of the right callback.
int copy_request_id_;
typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback;
typedef std::map<int, const CopyRequestCallback> CopyRequestMap;
CopyRequestMap copy_request_callbacks_;

typedef std::map<BrowserPluginGuest*, NewWindowInfo> PendingWindowMap;
PendingWindowMap pending_new_windows_;
base::WeakPtr<BrowserPluginGuest> opener_;
Expand Down
115 changes: 115 additions & 0 deletions content/browser/browser_plugin/browser_plugin_host_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -810,4 +810,119 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DoNotCrashOnInvalidNavigation) {
EXPECT_TRUE(delegate->load_aborted_url().is_valid());
}


// Tests involving the threaded compositor.
class BrowserPluginThreadedCompositorTest : public BrowserPluginHostTest {
public:
BrowserPluginThreadedCompositorTest() {}
virtual ~BrowserPluginThreadedCompositorTest() {}

protected:
virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
BrowserPluginHostTest::SetUpCommandLine(cmd);
cmd->AppendSwitch(switches::kEnableThreadedCompositing);

// http://crbug.com/327035
cmd->AppendSwitch(switches::kDisableDelegatedRenderer);
}
};

static void CompareSkBitmaps(const SkBitmap& expected_bitmap,
const SkBitmap& bitmap) {
EXPECT_EQ(expected_bitmap.width(), bitmap.width());
if (expected_bitmap.width() != bitmap.width())
return;
EXPECT_EQ(expected_bitmap.height(), bitmap.height());
if (expected_bitmap.height() != bitmap.height())
return;
EXPECT_EQ(expected_bitmap.config(), bitmap.config());
if (expected_bitmap.config() != bitmap.config())
return;

SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
SkAutoLockPixels bitmap_lock(bitmap);
int fails = 0;
const int kAllowableError = 2;
for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
SkColor expected_color = expected_bitmap.getColor(i, j);
SkColor color = bitmap.getColor(i, j);
int expected_alpha = SkColorGetA(expected_color);
int alpha = SkColorGetA(color);
int expected_red = SkColorGetR(expected_color);
int red = SkColorGetR(color);
int expected_green = SkColorGetG(expected_color);
int green = SkColorGetG(color);
int expected_blue = SkColorGetB(expected_color);
int blue = SkColorGetB(color);
EXPECT_NEAR(expected_alpha, alpha, kAllowableError)
<< "expected_color: " << std::hex << expected_color
<< " color: " << color
<< " Failed at " << std::dec << i << ", " << j
<< " Failure " << ++fails;
EXPECT_NEAR(expected_red, red, kAllowableError)
<< "expected_color: " << std::hex << expected_color
<< " color: " << color
<< " Failed at " << std::dec << i << ", " << j
<< " Failure " << ++fails;
EXPECT_NEAR(expected_green, green, kAllowableError)
<< "expected_color: " << std::hex << expected_color
<< " color: " << color
<< " Failed at " << std::dec << i << ", " << j
<< " Failure " << ++fails;
EXPECT_NEAR(expected_blue, blue, kAllowableError)
<< "expected_color: " << std::hex << expected_color
<< " color: " << color
<< " Failed at " << std::dec << i << ", " << j
<< " Failure " << ++fails;
}
}
EXPECT_LT(fails, 10);
}

static void CompareSkBitmapAndRun(const base::Closure& callback,
const SkBitmap& expected_bitmap,
bool *result,
bool succeed,
const SkBitmap& bitmap) {
*result = succeed;
if (succeed)
CompareSkBitmaps(expected_bitmap, bitmap);
callback.Run();
}

// http://crbug.com/171744
#if defined(OS_MACOSX)
#define MAYBE_GetBackingStore DISABLED_GetBackingStore
#else
#define MAYBE_GetBackingStore GetBackingStore
#endif
IN_PROC_BROWSER_TEST_F(BrowserPluginThreadedCompositorTest,
MAYBE_GetBackingStore) {
const char kEmbedderURL[] = "/browser_plugin_embedder.html";
const char kHTMLForGuest[] =
"data:text/html,<html><style>body { background-color: red; }</style>"
"<body></body></html>";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true,
std::string("SetSize(50, 60);"));

WebContentsImpl* guest_contents = test_guest()->web_contents();
RenderWidgetHostImpl* guest_widget_host =
RenderWidgetHostImpl::From(guest_contents->GetRenderViewHost());

SkBitmap expected_bitmap;
expected_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 50, 60);
expected_bitmap.allocPixels();
expected_bitmap.eraseARGB(255, 255, 0, 0); // #f00
bool result = false;
while (!result) {
base::RunLoop loop;
guest_widget_host->CopyFromBackingStore(gfx::Rect(),
guest_widget_host->GetView()->GetViewBounds().size(),
base::Bind(&CompareSkBitmapAndRun, loop.QuitClosure(), expected_bitmap,
&result));
loop.Run();
}
}

} // namespace content
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,10 @@ BackingStore* RenderWidgetHostViewGuest::AllocBackingStore(

void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& /* dst_size */,
const gfx::Size& dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback) {
callback.Run(false, SkBitmap());
CHECK(guest_);
guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback);
}

void RenderWidgetHostViewGuest::CopyFromCompositingSurfaceToVideoFrame(
Expand Down
12 changes: 12 additions & 0 deletions content/common/browser_plugin/browser_plugin_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
#include "ui/gfx/point.h"
Expand Down Expand Up @@ -212,6 +213,11 @@ IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_BuffersSwappedACK,
std::string /* mailbox_name */,
uint32 /* sync_point */)

IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
int /* instance_id */,
int /* request_id */,
SkBitmap);

// Acknowledge that we presented an ubercomp frame.
IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_CompositorFrameACK,
int /* instance_id */,
Expand Down Expand Up @@ -338,6 +344,12 @@ IPC_MESSAGE_CONTROL2(BrowserPluginMsg_UpdateRect,
int /* instance_id */,
BrowserPluginMsg_UpdateRect_Params)

IPC_MESSAGE_CONTROL4(BrowserPluginMsg_CopyFromCompositingSurface,
int /* instance_id */,
int /* request_id */,
gfx::Rect /* source_rect */,
gfx::Size /* dest_size */)

// Requests the renderer to find out if a browser plugin is at position
// (|x|, |y|) within the embedder.
// The response message is BrowserPluginHostMsg_PluginAtPositionResponse.
Expand Down
20 changes: 20 additions & 0 deletions content/renderer/browser_plugin/browser_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped)
IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped,
OnCompositorFrameSwapped(message))
IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface,
OnCopyFromCompositingSurface)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady,
OnGuestContentWindowReady)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
Expand Down Expand Up @@ -456,6 +458,23 @@ void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) {
param.e /* host_id */);
}

void BrowserPlugin::OnCopyFromCompositingSurface(int guest_instance_id,
int request_id,
gfx::Rect source_rect,
gfx::Size dest_size) {
if (!compositing_enabled_) {
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
render_view_routing_id_,
guest_instance_id_,
request_id,
SkBitmap()));
return;
}
compositing_helper_->CopyFromCompositingSurface(request_id, source_rect,
dest_size);
}

void BrowserPlugin::OnGuestContentWindowReady(int guest_instance_id,
int content_window_routing_id) {
DCHECK(content_window_routing_id != MSG_ROUTING_NONE);
Expand Down Expand Up @@ -1033,6 +1052,7 @@ bool BrowserPlugin::ShouldForwardToBrowserPlugin(
case BrowserPluginMsg_Attach_ACK::ID:
case BrowserPluginMsg_BuffersSwapped::ID:
case BrowserPluginMsg_CompositorFrameSwapped::ID:
case BrowserPluginMsg_CopyFromCompositingSurface::ID:
case BrowserPluginMsg_GuestContentWindowReady::ID:
case BrowserPluginMsg_GuestGone::ID:
case BrowserPluginMsg_SetCursor::ID:
Expand Down
4 changes: 4 additions & 0 deletions content/renderer/browser_plugin/browser_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ class CONTENT_EXPORT BrowserPlugin :
void OnBuffersSwapped(int instance_id,
const BrowserPluginMsg_BuffersSwapped_Params& params);
void OnCompositorFrameSwapped(const IPC::Message& message);
void OnCopyFromCompositingSurface(int instance_id,
int request_id,
gfx::Rect source_rect,
gfx::Size dest_size);
void OnGuestContentWindowReady(int instance_id,
int content_window_routing_id);
void OnGuestGone(int instance_id);
Expand Down
Loading

0 comments on commit 73405fb

Please sign in to comment.