diff options
author | fsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-26 23:53:32 +0000 |
---|---|---|
committer | fsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-26 23:53:32 +0000 |
commit | ffba8bf0d395da2eed0950891dafb6be849404f3 (patch) | |
tree | 1ae9e0fa24e41ac3fbda599adcd07293453e6ae3 | |
parent | 1b5c22b2f00f218b5e60a2cc945cf400d159c4bf (diff) | |
download | chromium_src-ffba8bf0d395da2eed0950891dafb6be849404f3.zip chromium_src-ffba8bf0d395da2eed0950891dafb6be849404f3.tar.gz chromium_src-ffba8bf0d395da2eed0950891dafb6be849404f3.tar.bz2 |
Browser Plugin: Implement asynchronous Resize and Autosize
Resize state is grouped into two sets of params:
BrowserPluginHostMsg_AutoSize_Params
BrowserPluginHostMsg_ResizeGuest_Params
As suggested by the names, the former is autosize state and the latter is standard resize state.
This patch enables asynchronous resize and autosize state pushes to the guest process from BrowserPlugin. It also supports flow control of these state pushes.
When updated autosize or resize state is pushed to the guest, the guest responds with a ViewHostMsg_UpdateRect that is then propagated to the BrowserPlugin via a BrowserPluginMsg_UpdateRect message.
When BrowserPlugin is resized, if there is no pending state push without an associated UpdateRect, then BrowserPlugin allocates an appropriately sized damage buffer |pending_damage_buffer_| and issues an asynchronous "SetAutoSize" or "ResizeGuest" to the browser process with a handle to the new damage buffer.
Every UpdateRect the BrowserPlugin receives holds a handle to the damage buffer that was used to copy pixels over to the embedder. Once the browser process begins to use the |pending_damage_buffer_| then the current damage buffer is dropped and the pending buffer becomes the current buffer.
If resize or autosize state changes in BrowserPlugin while there's a pending damage buffer, then no additional resize messages get sent. Instead, BrowserPlugin waits until an UpdateRect arrives that uses the pending buffer before pushing new state to the browser process, and guest.
BUG=155915
Review URL: https://chromiumcodereview.appspot.com/11369185
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169534 0039d316-1c4b-4281-b951-d872f2087c98
16 files changed, 441 insertions, 316 deletions
diff --git a/content/browser/browser_plugin/browser_plugin_embedder.cc b/content/browser/browser_plugin/browser_plugin_embedder.cc index 1338514..430bd56 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder.cc +++ b/content/browser/browser_plugin/browser_plugin_embedder.cc @@ -162,13 +162,14 @@ void BrowserPluginEmbedder::CreateGuest( CreateSwappedOutRenderView(web_contents()->GetSiteInstance()); render_view_host->Send(new BrowserPluginMsg_GuestContentWindowReady( render_view_host->GetRoutingID(), instance_id, guest_routing_id)); + + guest->SetSize(params.auto_size_params, params.resize_guest_params); } void BrowserPluginEmbedder::NavigateGuest( RenderViewHost* render_view_host, int instance_id, - const std::string& src, - const BrowserPluginHostMsg_ResizeGuest_Params& resize_params) { + const std::string& src) { BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); CHECK(guest); GURL url(src); @@ -190,17 +191,16 @@ void BrowserPluginEmbedder::NavigateGuest( PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); } - - // Resize the guest if the resize parameter was set from the renderer. - ResizeGuest(render_view_host, instance_id, resize_params); } -void BrowserPluginEmbedder::UpdateRectACK(int instance_id, - int message_id, - const gfx::Size& size) { +void BrowserPluginEmbedder::UpdateRectACK( + int instance_id, + int message_id, + const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, + const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); if (guest) - guest->UpdateRectACK(message_id, size); + guest->UpdateRectACK(message_id, auto_size_params, resize_guest_params); } void BrowserPluginEmbedder::ResizeGuest( @@ -301,7 +301,7 @@ void BrowserPluginEmbedder::SetAutoSize( const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); if (guest) - guest->SetAutoSize(auto_size_params, resize_guest_params); + guest->SetSize(auto_size_params, resize_guest_params); } void BrowserPluginEmbedder::Go(int instance_id, int relative_index) { diff --git a/content/browser/browser_plugin/browser_plugin_embedder.h b/content/browser/browser_plugin/browser_plugin_embedder.h index 3101824..bef0019 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder.h +++ b/content/browser/browser_plugin/browser_plugin_embedder.h @@ -78,8 +78,7 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver, void NavigateGuest( RenderViewHost* render_view_host, int instance_id, - const std::string& src, - const BrowserPluginHostMsg_ResizeGuest_Params& resize_params); + const std::string& src); void ResizeGuest(RenderViewHost* render_view_host, int instance_id, @@ -101,7 +100,11 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver, // Message handlers (direct/indirect via BrowserPluginEmbedderHelper). // Routes update rect ack message to the appropriate guest. - void UpdateRectACK(int instance_id, int message_id, const gfx::Size& size); + void UpdateRectACK( + int instance_id, + int message_id, + const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, + const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params); void SetFocus(int instance_id, bool focused); // Handles input events sent from the BrowserPlugin (embedder's renderer // process) by passing them to appropriate guest's input handler. diff --git a/content/browser/browser_plugin/browser_plugin_embedder_helper.cc b/content/browser/browser_plugin/browser_plugin_embedder_helper.cc index df8dfa2..0686cc7 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder_helper.cc +++ b/content/browser/browser_plugin/browser_plugin_embedder_helper.cc @@ -120,18 +120,19 @@ void BrowserPluginEmbedderHelper::OnCreateGuest( void BrowserPluginEmbedderHelper::OnNavigateGuest( int instance_id, - const std::string& src, - const BrowserPluginHostMsg_ResizeGuest_Params& resize_params) { - embedder_->NavigateGuest(render_view_host(), - instance_id, - src, - resize_params); -} - -void BrowserPluginEmbedderHelper::OnUpdateRectACK(int instance_id, - int message_id, - const gfx::Size& size) { - embedder_->UpdateRectACK(instance_id, message_id, size); + const std::string& src) { + embedder_->NavigateGuest(render_view_host(), instance_id, src); +} + +void BrowserPluginEmbedderHelper::OnUpdateRectACK( + int instance_id, + int message_id, + const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, + const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { + embedder_->UpdateRectACK(instance_id, + message_id, + auto_size_params, + resize_guest_params); } void BrowserPluginEmbedderHelper::OnSetFocus(int instance_id, bool focused) { diff --git a/content/browser/browser_plugin/browser_plugin_embedder_helper.h b/content/browser/browser_plugin/browser_plugin_embedder_helper.h index 678d1ca..1b2919c 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder_helper.h +++ b/content/browser/browser_plugin/browser_plugin_embedder_helper.h @@ -59,12 +59,14 @@ class BrowserPluginEmbedderHelper : public RenderViewHostObserver { // Message handlers. void OnCreateGuest(int instance_id, const BrowserPluginHostMsg_CreateGuest_Params& params); - void OnNavigateGuest(int instance_id, - const std::string& src, - const BrowserPluginHostMsg_ResizeGuest_Params& params); + void OnNavigateGuest(int instance_id, const std::string& src); void OnResizeGuest(int instance_id, const BrowserPluginHostMsg_ResizeGuest_Params& params); - void OnUpdateRectACK(int instance_id, int message_id, const gfx::Size& size); + void OnUpdateRectACK( + int instance_id, + int message_id, + const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, + const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params); void OnHandleInputEvent(const IPC::SyncMessage& message, bool* handled); void OnSetFocus(int instance_id, bool focused); void OnPluginDestroyed(int instance_id); diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 3af1c7a..7d763fb 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc @@ -50,6 +50,7 @@ BrowserPluginGuest::BrowserPluginGuest( instance_id_(instance_id), #if defined(OS_WIN) damage_buffer_size_(0), + remote_damage_buffer_handle_(0), #endif damage_buffer_scale_factor_(1.0f), pending_update_counter_(0), @@ -57,9 +58,9 @@ BrowserPluginGuest::BrowserPluginGuest( base::TimeDelta::FromMilliseconds(kGuestHangTimeoutMs)), focused_(params.focused), visible_(params.visible), - auto_size_(params.auto_size.enable), - max_auto_size_(params.auto_size.max_size), - min_auto_size_(params.auto_size.min_size) { + auto_size_enabled_(params.auto_size_params.enable), + max_auto_size_(params.auto_size_params.max_size), + min_auto_size_(params.auto_size_params.min_size) { DCHECK(web_contents); // |render_view_host| manages the ownership of this BrowserPluginGuestHelper. new BrowserPluginGuestHelper(this, render_view_host); @@ -196,20 +197,34 @@ void BrowserPluginGuest::DragStatusUpdate(WebKit::WebDragStatus drag_status, } } -void BrowserPluginGuest::SetAutoSize( +void BrowserPluginGuest::SetSize( const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { - auto_size_ = auto_size_params.enable; + bool old_auto_size_enabled = auto_size_enabled_; + gfx::Size old_max_size = max_auto_size_; + gfx::Size old_min_size = min_auto_size_; + auto_size_enabled_ = auto_size_params.enable; max_auto_size_ = auto_size_params.max_size; min_auto_size_ = auto_size_params.min_size; - if (auto_size_) { + if (auto_size_enabled_ && (!old_auto_size_enabled || + (old_max_size != max_auto_size_) || + (old_min_size != min_auto_size_))) { web_contents()->GetRenderViewHost()->EnableAutoResize( min_auto_size_, max_auto_size_); - } else { + // TODO(fsamuel): If we're changing autosize parameters, then we force + // the guest to completely repaint itself, because BrowserPlugin has + // allocated a new damage buffer and expects a full frame of pixels. + // Ideally, we shouldn't need to do this because we shouldn't need to + // allocate a new damage buffer unless |max_auto_size_| has changed. + // However, even in that case, layout may not change and so we may + // not get a full frame worth of pixels. + web_contents()->GetRenderViewHost()->Send(new ViewMsg_Repaint( + web_contents()->GetRenderViewHost()->GetRoutingID(), + max_auto_size_)); + } else if (!auto_size_enabled_ && old_auto_size_enabled) { web_contents()->GetRenderViewHost()->DisableAutoResize( - gfx::Size(resize_guest_params.width, resize_guest_params.height)); + resize_guest_params.view_size); } - // We call resize here to update the damage buffer. Resize(embedder_web_contents_->GetRenderViewHost(), resize_guest_params); } @@ -238,12 +253,16 @@ void BrowserPluginGuest::Terminate() { void BrowserPluginGuest::Resize( RenderViewHost* embedder_rvh, const BrowserPluginHostMsg_ResizeGuest_Params& params) { + // BrowserPlugin manages resize flow control itself and does not depend + // on RenderWidgetHost's mechanisms for flow control, so we reset those flags + // here. + RenderWidgetHostImpl* render_widget_host = + RenderWidgetHostImpl::From(web_contents()->GetRenderViewHost()); + render_widget_host->ResetSizeAndRepaintPendingFlags(); if (!TransportDIB::is_valid_id(params.damage_buffer_id)) { // Invalid transport dib, so just resize the WebContents. - if (params.width && params.height) { - web_contents()->GetView()->SizeContents(gfx::Size(params.width, - params.height)); - } + if (!params.view_size.IsEmpty()) + web_contents()->GetView()->SizeContents(params.view_size); return; } TransportDIB* damage_buffer = @@ -251,13 +270,11 @@ void BrowserPluginGuest::Resize( SetDamageBuffer(damage_buffer, #if defined(OS_WIN) params.damage_buffer_size, + params.damage_buffer_id.handle, #endif - gfx::Size(params.width, params.height), + params.view_size, params.scale_factor); - if (!params.resize_pending) { - web_contents()->GetView()->SizeContents(gfx::Size(params.width, - params.height)); - } + web_contents()->GetView()->SizeContents(params.view_size); } TransportDIB* BrowserPluginGuest::GetDamageBufferFromEmbedder( @@ -291,6 +308,7 @@ void BrowserPluginGuest::SetDamageBuffer( TransportDIB* damage_buffer, #if defined(OS_WIN) int damage_buffer_size, + TransportDIB::Handle remote_handle, #endif const gfx::Size& damage_view_size, float scale_factor) { @@ -300,6 +318,7 @@ void BrowserPluginGuest::SetDamageBuffer( damage_buffer_.reset(damage_buffer); #if defined(OS_WIN) damage_buffer_size_ = damage_buffer_size; + remote_damage_buffer_handle_ = remote_handle; #endif damage_view_size_ = damage_view_size; damage_buffer_scale_factor_ = scale_factor; @@ -317,9 +336,6 @@ bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const { void BrowserPluginGuest::UpdateRect( RenderViewHost* render_view_host, const ViewHostMsg_UpdateRect_Params& params) { - RenderWidgetHostImpl* render_widget_host = - RenderWidgetHostImpl::From(render_view_host); - render_widget_host->ResetSizeAndRepaintPendingFlags(); // This handler is only of interest to us for the 2D software rendering path. // needs_ack should always be true for the 2D path. // TODO(fsamuel): Do we need to do something different in the 3D case? @@ -332,7 +348,7 @@ void BrowserPluginGuest::UpdateRect( // buffer's scale factor. // The scaling change can happen due to asynchronous updates of the DPI on a // resolution change. - if (((auto_size_ && InAutoSizeBounds(params.view_size)) || + 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.scale_factor == damage_buffer_scale_factor()) { @@ -355,6 +371,15 @@ void BrowserPluginGuest::UpdateRect( } } BrowserPluginMsg_UpdateRect_Params relay_params; +#if defined(OS_MACOSX) + relay_params.damage_buffer_identifier = damage_buffer_->id(); +#elif defined(OS_WIN) + // On Windows, the handle used locally differs from the handle received from + // the embedder process, since we duplicate the remote handle. + relay_params.damage_buffer_identifier = remote_damage_buffer_handle_; +#else + relay_params.damage_buffer_identifier = damage_buffer_->handle(); +#endif relay_params.bitmap_rect = params.bitmap_rect; relay_params.scroll_delta = params.scroll_delta; relay_params.scroll_rect = params.scroll_rect; @@ -369,26 +394,25 @@ void BrowserPluginGuest::UpdateRect( int message_id = pending_update_counter_++; pending_updates_.AddWithID(render_view_host, message_id); - gfx::Size param_size = gfx::Size(params.view_size.width(), - params.view_size.height()); - SendMessageToEmbedder(new BrowserPluginMsg_UpdateRect(embedder_routing_id(), instance_id(), message_id, relay_params)); } -void BrowserPluginGuest::UpdateRectACK(int message_id, const gfx::Size& size) { +void BrowserPluginGuest::UpdateRectACK( + int message_id, + const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, + const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { RenderViewHost* render_view_host = pending_updates_.Lookup(message_id); // If the guest has crashed since it sent the initial ViewHostMsg_UpdateRect // then the pending_updates_ map will have been cleared. - if (!render_view_host) - return; - pending_updates_.Remove(message_id); - render_view_host->Send( - new ViewMsg_UpdateRect_ACK(render_view_host->GetRoutingID())); - if (!size.IsEmpty()) - render_view_host->GetView()->SetSize(size); + if (render_view_host) { + pending_updates_.Remove(message_id); + render_view_host->Send( + new ViewMsg_UpdateRect_ACK(render_view_host->GetRoutingID())); + } + SetSize(auto_size_params, resize_guest_params); } void BrowserPluginGuest::HandleInputEvent(RenderViewHost* render_view_host, @@ -565,7 +589,7 @@ void BrowserPluginGuest::RenderViewReady() { bool embedder_visible = embedder_web_contents_->GetBrowserPluginEmbedder()->visible(); SetVisibility(embedder_visible, visible()); - if (auto_size_) { + if (auto_size_enabled_) { web_contents()->GetRenderViewHost()->EnableAutoResize( min_auto_size_, max_auto_size_); } else { diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h index d92a2d319..b0a5d7a 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.h +++ b/content/browser/browser_plugin/browser_plugin_guest.h @@ -41,11 +41,11 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebDragStatus.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h" #include "ui/gfx/rect.h" +#include "ui/surface/transport_dib.h" struct BrowserPluginHostMsg_AutoSize_Params; struct BrowserPluginHostMsg_CreateGuest_Params; struct BrowserPluginHostMsg_ResizeGuest_Params; -class TransportDIB; struct ViewHostMsg_UpdateRect_Params; class WebCursor; struct WebDropData; @@ -137,7 +137,10 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, void UpdateRect(RenderViewHost* render_view_host, const ViewHostMsg_UpdateRect_Params& params); - void UpdateRectACK(int message_id, const gfx::Size& size); + void UpdateRectACK( + int message_id, + const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, + const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params); // Overrides default ShowWidget message so we show them on the correct // coordinates. void ShowWidget(RenderViewHost* render_view_host, @@ -179,8 +182,8 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, WebKit::WebDragOperationsMask drag_mask, const gfx::Point& location); - // Updates the autosize state of the guest. - void SetAutoSize( + // Updates the size state of the guest. + void SetSize( const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params); @@ -222,6 +225,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, virtual void SetDamageBuffer(TransportDIB* damage_buffer, #if defined(OS_WIN) int damage_buffer_size, + TransportDIB::Handle remote_handle, #endif const gfx::Size& damage_view_size, float scale_factor); @@ -271,6 +275,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, scoped_ptr<TransportDIB> damage_buffer_; #if defined(OS_WIN) size_t damage_buffer_size_; + TransportDIB::Handle remote_damage_buffer_handle_; #endif gfx::Size damage_view_size_; float damage_buffer_scale_factor_; @@ -281,7 +286,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, base::TimeDelta guest_hang_timeout_; bool focused_; bool visible_; - bool auto_size_; + bool auto_size_enabled_; gfx::Size max_auto_size_; gfx::Size min_auto_size_; diff --git a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc index cb3a6f4..9a0c74c 100644 --- a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc +++ b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc @@ -1192,7 +1192,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AutoSizeAfterNavigation) { EXPECT_EQ(expected_title, actual_title); } { - // Turn off autoSize and verify that the guest resizes to fit the contaienr. + // 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)); diff --git a/content/browser/browser_plugin/test_browser_plugin_guest.cc b/content/browser/browser_plugin/test_browser_plugin_guest.cc index 1417994..1f2d017 100644 --- a/content/browser/browser_plugin/test_browser_plugin_guest.cc +++ b/content/browser/browser_plugin/test_browser_plugin_guest.cc @@ -272,6 +272,7 @@ void TestBrowserPluginGuest::SetDamageBuffer( TransportDIB* damage_buffer, #if defined(OS_WIN) int damage_buffer_size, + TransportDIB::Handle remote_handle, #endif const gfx::Size& damage_view_size, float scale_factor) { @@ -289,6 +290,7 @@ void TestBrowserPluginGuest::SetDamageBuffer( damage_buffer, #if defined(OS_WIN) damage_buffer_size, + remote_handle, #endif damage_view_size, scale_factor); diff --git a/content/browser/browser_plugin/test_browser_plugin_guest.h b/content/browser/browser_plugin/test_browser_plugin_guest.h index 80f0c8b..f5d2691 100644 --- a/content/browser/browser_plugin/test_browser_plugin_guest.h +++ b/content/browser/browser_plugin/test_browser_plugin_guest.h @@ -49,6 +49,7 @@ class TestBrowserPluginGuest : public BrowserPluginGuest { virtual void SetDamageBuffer(TransportDIB* damage_buffer, #if defined(OS_WIN) int damage_buffer_size, + TransportDIB::Handle remote_handle, #endif const gfx::Size& damage_view_size, float scale_factor) OVERRIDE; diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index a1a889c..60edf72 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc @@ -927,8 +927,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) { // TODO(fsamuel): Disallow BrowserPluginHostMsg_* sync messages to run on UI // thread and make these messages async: http://crbug.com/149063. if (msg.type() != BrowserPluginHostMsg_HandleInputEvent::ID && - msg.type() != BrowserPluginHostMsg_ResizeGuest::ID && - msg.type() != BrowserPluginHostMsg_SetAutoSize::ID && !BrowserMessageFilter::CheckCanDispatchOnUI(msg, this)) return true; diff --git a/content/common/browser_plugin_messages.h b/content/common/browser_plugin_messages.h index 782b9a3..b14d1b2 100644 --- a/content/common/browser_plugin_messages.h +++ b/content/common/browser_plugin_messages.h @@ -35,14 +35,6 @@ IPC_STRUCT_BEGIN(BrowserPluginHostMsg_AutoSize_Params) IPC_STRUCT_MEMBER(gfx::Size, min_size) IPC_STRUCT_END() -IPC_STRUCT_BEGIN(BrowserPluginHostMsg_CreateGuest_Params) - IPC_STRUCT_MEMBER(std::string, storage_partition_id) - IPC_STRUCT_MEMBER(bool, persist_storage) - IPC_STRUCT_MEMBER(bool, focused) - IPC_STRUCT_MEMBER(bool, visible) - IPC_STRUCT_MEMBER(BrowserPluginHostMsg_AutoSize_Params, auto_size) -IPC_STRUCT_END() - IPC_STRUCT_BEGIN(BrowserPluginHostMsg_ResizeGuest_Params) // An identifier to the new buffer to use to transport damage to the embedder // renderer process. @@ -57,17 +49,22 @@ IPC_STRUCT_BEGIN(BrowserPluginHostMsg_ResizeGuest_Params) // on Windows. IPC_STRUCT_MEMBER(int, damage_buffer_size) #endif - // The new width of the plugin container. - IPC_STRUCT_MEMBER(int, width) - // The new height of the plugin container. - IPC_STRUCT_MEMBER(int, height) - // Indicates whether the embedder is currently waiting on a ACK from the - // guest for a previous resize request. - IPC_STRUCT_MEMBER(bool, resize_pending) + // The new size of the guest view area. + IPC_STRUCT_MEMBER(gfx::Size, view_size) // Indicates the scale factor of the embedder WebView. IPC_STRUCT_MEMBER(float, scale_factor) IPC_STRUCT_END() +IPC_STRUCT_BEGIN(BrowserPluginHostMsg_CreateGuest_Params) + IPC_STRUCT_MEMBER(std::string, storage_partition_id) + IPC_STRUCT_MEMBER(bool, persist_storage) + IPC_STRUCT_MEMBER(bool, focused) + IPC_STRUCT_MEMBER(bool, visible) + IPC_STRUCT_MEMBER(BrowserPluginHostMsg_AutoSize_Params, auto_size_params) + IPC_STRUCT_MEMBER(BrowserPluginHostMsg_ResizeGuest_Params, + resize_guest_params) +IPC_STRUCT_END() + IPC_STRUCT_BEGIN(BrowserPluginMsg_LoadCommit_Params) // The current URL of the guest. IPC_STRUCT_MEMBER(GURL, url) @@ -83,6 +80,14 @@ IPC_STRUCT_BEGIN(BrowserPluginMsg_LoadCommit_Params) IPC_STRUCT_END() IPC_STRUCT_BEGIN(BrowserPluginMsg_UpdateRect_Params) + // The bitmap to be painted into the view at the locations specified by + // update_rects. +#if defined(OS_MACOSX) + IPC_STRUCT_MEMBER(TransportDIB::Id, damage_buffer_identifier) +#else + IPC_STRUCT_MEMBER(TransportDIB::Handle, damage_buffer_identifier) +#endif + // The position and size of the bitmap. IPC_STRUCT_MEMBER(gfx::Rect, bitmap_rect) @@ -123,7 +128,7 @@ IPC_STRUCT_END() // This message is sent to the browser process to enable or disable autosize // mode. -IPC_SYNC_MESSAGE_ROUTED3_0( +IPC_MESSAGE_ROUTED3( BrowserPluginHostMsg_SetAutoSize, int /* instance_id */, BrowserPluginHostMsg_AutoSize_Params /* auto_size_params */, @@ -172,20 +177,20 @@ IPC_SYNC_MESSAGE_ROUTED0_1(BrowserPluginHostMsg_HandleInputEvent, // the previous frame and is ready for the next frame. If the guest sent the // embedder a bitmap that does not match the size of the BrowserPlugin's // container, the BrowserPlugin requests a new size as well. -IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_UpdateRect_ACK, - int /* instance_id */, - int /* message_id */, - gfx::Size /* repaint_view_size */) +IPC_MESSAGE_ROUTED4(BrowserPluginHostMsg_UpdateRect_ACK, + int /* instance_id */, + int /* message_id */, + BrowserPluginHostMsg_AutoSize_Params /* auto_size_params */, + BrowserPluginHostMsg_ResizeGuest_Params /* resize_guest_params */) // A BrowserPlugin sends this to BrowserPluginEmbedder (browser process) when it // wants to navigate to a given src URL. If a guest WebContents already exists, // it will navigate that WebContents. If not, it will create the WebContents, // associate it with the BrowserPluginGuest, and navigate it to the requested // URL. -IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_NavigateGuest, +IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_NavigateGuest, int /* instance_id*/, - std::string /* src */, - BrowserPluginHostMsg_ResizeGuest_Params /* resize_params */) + std::string /* src */) // When a BrowserPlugin has been removed from the embedder's DOM, it informs // the browser process to cleanup the guest. @@ -218,9 +223,9 @@ IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_PluginAtPositionResponse, // A embedder sends this message to the browser when it wants // to resize a guest plugin container so that the guest is relaid out // according to the new size. -IPC_SYNC_MESSAGE_ROUTED2_0(BrowserPluginHostMsg_ResizeGuest, - int /* instance_id*/, - BrowserPluginHostMsg_ResizeGuest_Params) +IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ResizeGuest, + int /* instance_id*/, + BrowserPluginHostMsg_ResizeGuest_Params) // ----------------------------------------------------------------------------- // These messages are from the browser process to the embedder. diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 87647af..e5178b0 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc @@ -103,10 +103,10 @@ BrowserPlugin::BrowserPlugin( render_view_(render_view->AsWeakPtr()), render_view_routing_id_(render_view->GetRoutingID()), container_(NULL), - damage_buffer_(NULL), + current_damage_buffer_(NULL), + pending_damage_buffer_(NULL), sad_guest_(NULL), guest_crashed_(false), - resize_pending_(false), navigate_src_sent_(false), auto_size_(false), max_height_(0), @@ -131,8 +131,10 @@ BrowserPlugin::BrowserPlugin( } BrowserPlugin::~BrowserPlugin() { - if (damage_buffer_) - FreeDamageBuffer(); + if (current_damage_buffer_) + FreeDamageBuffer(¤t_damage_buffer_); + if (pending_damage_buffer_) + FreeDamageBuffer(&pending_damage_buffer_); browser_plugin_manager()->RemoveBrowserPlugin(instance_id_); browser_plugin_manager()->Send( new BrowserPluginHostMsg_PluginDestroyed( @@ -141,8 +143,10 @@ BrowserPlugin::~BrowserPlugin() { } void BrowserPlugin::Cleanup() { - if (damage_buffer_) - FreeDamageBuffer(); + if (current_damage_buffer_) + FreeDamageBuffer(¤t_damage_buffer_); + if (pending_damage_buffer_) + FreeDamageBuffer(&pending_damage_buffer_); } bool BrowserPlugin::SetSrcAttribute(const std::string& src, @@ -159,29 +163,26 @@ bool BrowserPlugin::SetSrcAttribute(const std::string& src, // after creation. If |src| is empty, we can delay the creation until we // acutally need it. if (!navigate_src_sent_) { - BrowserPluginHostMsg_CreateGuest_Params params; - params.storage_partition_id = storage_partition_id_; - params.persist_storage = persist_storage_; - params.focused = ShouldGuestBeFocused(); - params.visible = visible_; - PopulateAutoSizeParameters(¶ms.auto_size); + BrowserPluginHostMsg_CreateGuest_Params create_guest_params; + create_guest_params.storage_partition_id = storage_partition_id_; + create_guest_params.persist_storage = persist_storage_; + create_guest_params.focused = ShouldGuestBeFocused(); + create_guest_params.visible = visible_; + pending_damage_buffer_ = + GetDamageBufferWithSizeParams(&create_guest_params.auto_size_params, + &create_guest_params.resize_guest_params); browser_plugin_manager()->Send( new BrowserPluginHostMsg_CreateGuest( render_view_routing_id_, instance_id_, - params)); + create_guest_params)); } - scoped_ptr<BrowserPluginHostMsg_ResizeGuest_Params> params( - GetPendingResizeParams()); - DCHECK(!params->resize_pending); - browser_plugin_manager()->Send( new BrowserPluginHostMsg_NavigateGuest( render_view_routing_id_, instance_id_, - src, - *params)); + src)); // Record that we sent a NavigateGuest message to embedder. // Once this instance has navigated, the storage partition cannot be changed, // so this value is used for enforcing this. @@ -213,31 +214,20 @@ void BrowserPlugin::PopulateAutoSizeParameters( } void BrowserPlugin::UpdateGuestAutoSizeState() { - if (!navigate_src_sent_) + // If we haven't yet heard back from the guest about the last resize request, + // then we don't issue another request until we do in + // BrowserPlugin::UpdateRect. + if (!navigate_src_sent_ || pending_damage_buffer_) return; BrowserPluginHostMsg_AutoSize_Params auto_size_params; - PopulateAutoSizeParameters(&auto_size_params); - BrowserPluginHostMsg_ResizeGuest_Params resize_params; - int view_width = auto_size_params.max_size.width(); - int view_height = auto_size_params.max_size.height(); - if (!auto_size_params.enable) { - view_width = width(); - view_height = height(); - } - TransportDIB* new_damage_buffer = - PopulateResizeGuestParameters(&resize_params, view_width, view_height); - // AutoSize initiates a resize so we don't want to issue another resize, - // we just want to make sure the damage buffer has been updated. - resize_params.resize_pending = true; - DCHECK(new_damage_buffer); + BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params; + pending_damage_buffer_ = + GetDamageBufferWithSizeParams(&auto_size_params, &resize_guest_params); browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetAutoSize( render_view_routing_id_, instance_id_, auto_size_params, - resize_params)); - if (damage_buffer_) - FreeDamageBuffer(); - damage_buffer_ = new_damage_buffer; + resize_guest_params)); } void BrowserPlugin::SizeChangedDueToAutoSize(const gfx::Size& old_view_size) { @@ -251,6 +241,24 @@ void BrowserPlugin::SizeChangedDueToAutoSize(const gfx::Size& old_view_size) { TriggerEvent(kEventSizeChanged, &props); } +#if defined(OS_MACOSX) +bool BrowserPlugin::DamageBufferMatches( + const TransportDIB* damage_buffer, + const TransportDIB::Id& other_damage_buffer_id) { + if (!damage_buffer) + return false; + return damage_buffer->id() == other_damage_buffer_id; +} +#else +bool BrowserPlugin::DamageBufferMatches( + const TransportDIB* damage_buffer, + const TransportDIB::Handle& other_damage_buffer_handle) { + if (!damage_buffer) + return false; + return damage_buffer->handle() == other_damage_buffer_handle; +} +#endif + void BrowserPlugin::SetMaxHeightAttribute(int max_height) { if (max_height_ == max_height) return; @@ -471,18 +479,43 @@ void BrowserPlugin::SetCursor(const WebCursor& cursor) { void BrowserPlugin::UpdateRect( int message_id, const BrowserPluginMsg_UpdateRect_Params& params) { + bool use_new_damage_buffer = !backing_store_; + BrowserPluginHostMsg_AutoSize_Params auto_size_params; + BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params; + // If we have a pending damage buffer, and the guest has begun to use the + // damage buffer then we know the guest will no longer use the current + // damage buffer. At this point, we drop the current damage buffer, and + // mark the pending damage buffer as the current damage buffer. + if (DamageBufferMatches(pending_damage_buffer_, + params.damage_buffer_identifier)) { + SwapDamageBuffers(); + use_new_damage_buffer = true; + } if ((!auto_size_ && (width() != params.view_size.width() || height() != params.view_size.height())) || (auto_size_ && (!InAutoSizeBounds(params.view_size)))) { + if (pending_damage_buffer_) { + // The guest has not yet responded to the last resize request, and + // so we don't want to do anything at this point other than ACK the guest. + PopulateAutoSizeParameters(&auto_size_params); + } else { + // If we have no pending damage buffer, then the guest has not caught up + // with the BrowserPlugin container. We now tell the guest about the new + // container size. + pending_damage_buffer_ = + GetDamageBufferWithSizeParams(&auto_size_params, + &resize_guest_params); + } browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateRect_ACK( render_view_routing_id_, instance_id_, message_id, - gfx::Size(width(), height()))); + auto_size_params, + resize_guest_params)); return; } - // If the view size has changed since we last updated. + if (auto_size_ && (params.view_size != last_view_size_)) { if (backing_store_) backing_store_->Clear(SK_ColorWHITE); @@ -493,7 +526,7 @@ void BrowserPlugin::UpdateRect( // resize to avoid flicker. |size_changed_in_flight_| acts as a form of // flow control for SizeChanged events. If the guest's view size is changing // rapidly before a SizeChanged event fires, then we avoid scheduling - // another SizedChanged event. SizedChanged reads the new size from + // another SizeChanged event. SizeChanged reads the new size from // |last_view_size_| so we can be sure that it always fires an event // with the last seen view size. if (container_ && !size_changed_in_flight_) { @@ -503,19 +536,15 @@ void BrowserPlugin::UpdateRect( base::Bind(&BrowserPlugin::SizeChangedDueToAutoSize, base::Unretained(this), old_view_size)); - } + } } - float backing_store_scale_factor = - backing_store_.get() ? backing_store_->GetScaleFactor() : 1.0f; - - if (!backing_store_ || params.is_resize_ack || - (backing_store_scale_factor != params.scale_factor) || - params.view_size.width() > backing_store_->GetSize().width() || - params.view_size.height() > backing_store_->GetSize().height()) { + // If we are now using a new damage buffer, then that means that the guest + // has updated its size state in response to a resize request. We change + // the backing store's size to accomodate the new damage buffer size. + if (use_new_damage_buffer) { int backing_store_width = auto_size_ ? max_width_ : width(); int backing_store_height = auto_size_ ? max_height_: height(); - resize_pending_ = !params.is_resize_ack; backing_store_.reset( new BrowserPluginBackingStore( gfx::Size(backing_store_width, backing_store_height), @@ -531,18 +560,20 @@ void BrowserPlugin::UpdateRect( for (unsigned i = 0; i < params.copy_rects.size(); i++) { backing_store_->PaintToBackingStore(params.bitmap_rect, params.copy_rects, - damage_buffer_); + current_damage_buffer_); } // Invalidate the container. // If the BrowserPlugin is scheduled to be deleted, then container_ will be // NULL so we shouldn't attempt to access it. if (container_) container_->invalidate(); + PopulateAutoSizeParameters(&auto_size_params); browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateRect_ACK( render_view_routing_id_, instance_id_, message_id, - gfx::Size())); + auto_size_params, + resize_guest_params)); } void BrowserPlugin::GuestGone(int process_id, base::TerminationStatus status) { @@ -631,10 +662,10 @@ void BrowserPlugin::SetEmbedderFocus(bool focused) { embedder_focused_ = focused; if (ShouldGuestBeFocused() != old_guest_focus_state) - UpdateGuestFocus(); + UpdateGuestFocusState(); } -void BrowserPlugin::UpdateGuestFocus() { +void BrowserPlugin::UpdateGuestFocusState() { if (!navigate_src_sent_) return; bool should_be_focused = ShouldGuestBeFocused(); @@ -745,65 +776,59 @@ void BrowserPlugin::updateGeometry( int old_width = width(); int old_height = height(); plugin_rect_ = window_rect; - if (auto_size_ || (old_width == window_rect.width && - old_height == window_rect.height)) { + // In AutoSize mode, guests don't care when the BrowserPlugin container is + // resized. If |pending_damage_buffer_|, 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. + if (!navigate_src_sent_ || auto_size_ || pending_damage_buffer_ || + (old_width == window_rect.width && + old_height == window_rect.height)) { return; } - pending_resize_params_.reset(); - scoped_ptr<BrowserPluginHostMsg_ResizeGuest_Params> params( - new BrowserPluginHostMsg_ResizeGuest_Params); - - TransportDIB* new_damage_buffer = - PopulateResizeGuestParameters(params.get(), width(), height()); - DCHECK(new_damage_buffer); - - if (navigate_src_sent_) { - browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest( - render_view_routing_id_, - instance_id_, - *params)); - resize_pending_ = true; - } else { - // Until an actual navigation occurs, there is no browser-side embedder - // present to notify about geometry updates. In this case, after we've - // updated the BrowserPlugin's state we are done and we do not send a resize - // message to the browser. - pending_resize_params_.reset(params.release()); - } - if (damage_buffer_) - FreeDamageBuffer(); - damage_buffer_ = new_damage_buffer; + BrowserPluginHostMsg_ResizeGuest_Params params; + pending_damage_buffer_ = + PopulateResizeGuestParameters(¶ms, gfx::Size(width(), height())); + browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest( + render_view_routing_id_, + instance_id_, + params)); } -void BrowserPlugin::FreeDamageBuffer() { - DCHECK(damage_buffer_); +void BrowserPlugin::FreeDamageBuffer(TransportDIB** damage_buffer) { + DCHECK(damage_buffer); + DCHECK(*damage_buffer); #if defined(OS_MACOSX) // We don't need to (nor should we) send ViewHostMsg_FreeTransportDIB // message to the browser to free the damage buffer since we manage the // damage buffer ourselves. - delete damage_buffer_; + delete *damage_buffer; #else - RenderProcess::current()->FreeTransportDIB(damage_buffer_); - damage_buffer_ = NULL; + RenderProcess::current()->FreeTransportDIB(*damage_buffer); + *damage_buffer = NULL; #endif } +void BrowserPlugin::SwapDamageBuffers() { + if (current_damage_buffer_) + FreeDamageBuffer(¤t_damage_buffer_); + current_damage_buffer_ = pending_damage_buffer_; + pending_damage_buffer_ = NULL; +} + TransportDIB* BrowserPlugin::PopulateResizeGuestParameters( BrowserPluginHostMsg_ResizeGuest_Params* params, - int view_width, int view_height) { - const size_t stride = skia::PlatformCanvasStrideForWidth(view_width); + const gfx::Size& view_size) { + const size_t stride = skia::PlatformCanvasStrideForWidth(view_size.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_height * + static_cast<size_t>(view_size.height() * stride * GetDeviceScaleFactor() * GetDeviceScaleFactor())); - // Don't drop the old damage buffer until after we've made sure that the - // browser process has dropped it. TransportDIB* new_damage_buffer = CreateTransportDIB(size); params->damage_buffer_id = new_damage_buffer->id(); #if defined(OS_MACOSX) @@ -815,30 +840,20 @@ TransportDIB* BrowserPlugin::PopulateResizeGuestParameters( #if defined(OS_WIN) params->damage_buffer_size = size; #endif - params->width = view_width; - params->height = view_height; - params->resize_pending = resize_pending_; + params->view_size = view_size; params->scale_factor = GetDeviceScaleFactor(); return new_damage_buffer; } -BrowserPluginHostMsg_ResizeGuest_Params* - BrowserPlugin::GetPendingResizeParams() { - if (pending_resize_params_.get()) { - resize_pending_ = true; - return pending_resize_params_.release(); - } else { - BrowserPluginHostMsg_ResizeGuest_Params* params = - new BrowserPluginHostMsg_ResizeGuest_Params; - - // We don't have a pending resize to send, so we send an invalid transport - // dib Id. - params->damage_buffer_id = TransportDIB::Id(); - params->width = width(); - params->height = height(); - params->resize_pending = false; - return params; - } +TransportDIB* BrowserPlugin::GetDamageBufferWithSizeParams( + BrowserPluginHostMsg_AutoSize_Params* auto_size_params, + BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params) { + PopulateAutoSizeParameters(auto_size_params); + gfx::Size view_size = auto_size_params->enable ? auto_size_params->max_size : + gfx::Size(width(), height()); + if (view_size.IsEmpty()) + return NULL; + return PopulateResizeGuestParameters(resize_guest_params, view_size); } TransportDIB* BrowserPlugin::CreateTransportDIB(const size_t size) { @@ -877,7 +892,7 @@ void BrowserPlugin::updateFocus(bool focused) { plugin_focused_ = focused; if (ShouldGuestBeFocused() != old_guest_focus_state) - UpdateGuestFocus(); + UpdateGuestFocusState(); } void BrowserPlugin::updateVisibility(bool visible) { diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h index caf1c28..0c43644 100644 --- a/content/renderer/browser_plugin/browser_plugin.h +++ b/content/renderer/browser_plugin/browser_plugin.h @@ -103,7 +103,7 @@ class CONTENT_EXPORT BrowserPlugin : // Inform the BrowserPlugin of the focus state of the embedder RenderView. void SetEmbedderFocus(bool focused); // Informs the guest of an updated focus state. - void UpdateGuestFocus(); + void UpdateGuestFocusState(); // Indicates whether the guest should be focused. bool ShouldGuestBeFocused() const; @@ -214,10 +214,6 @@ class CONTENT_EXPORT BrowserPlugin : // and sets them appropriately. void ParseAttributes(const WebKit::WebPluginParams& params); - // Returns the pending resize guest param if there is one. Returns a param - // with invalid transport dib otherwise. - BrowserPluginHostMsg_ResizeGuest_Params* GetPendingResizeParams(); - // Initializes the valid events. void InitializeEvents(); @@ -236,23 +232,41 @@ class CONTENT_EXPORT BrowserPlugin : // Creates and maps transport dib. Overridden in tests. virtual TransportDIB* CreateTransportDIB(const size_t size); // Frees up the damage buffer. Overridden in tests. - virtual void FreeDamageBuffer(); + virtual void FreeDamageBuffer(TransportDIB** damage_buffer); + // Swaps out the |current_damage_buffer_| with the |pending_damage_buffer_|. + void SwapDamageBuffers(); + // Populates BrowserPluginHostMsg_ResizeGuest_Params with resize state and // returns the newly allocated TransportDIB. TransportDIB* PopulateResizeGuestParameters( BrowserPluginHostMsg_ResizeGuest_Params* params, - int view_width, int view_height); + const gfx::Size& view_size); // Populates BrowserPluginHostMsg_AutoSize_Params object with autosize state. void PopulateAutoSizeParameters( BrowserPluginHostMsg_AutoSize_Params* params); + // Populates both AutoSize and ResizeGuest parameters based on the current + // autosize state. + TransportDIB* GetDamageBufferWithSizeParams( + BrowserPluginHostMsg_AutoSize_Params* auto_size_params, + BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params); + // Informs the guest of an updated autosize state. void UpdateGuestAutoSizeState(); // Informs the BrowserPlugin that guest has changed its size in autosize mode. void SizeChangedDueToAutoSize(const gfx::Size& old_view_size); +#if defined(OS_MACOSX) + bool DamageBufferMatches(const TransportDIB* damage_buffer, + const TransportDIB::Id& other_damage_buffer_id); +#else + bool DamageBufferMatches( + const TransportDIB* damage_buffer, + const TransportDIB::Handle& other_damage_buffer_handle); +#endif + int instance_id_; base::WeakPtr<RenderViewImpl> render_view_; // We cache the |render_view_|'s routing ID because we need it on destruction. @@ -262,12 +276,12 @@ class CONTENT_EXPORT BrowserPlugin : WebKit::WebPluginContainer* container_; scoped_ptr<BrowserPluginBindings> bindings_; scoped_ptr<BrowserPluginBackingStore> backing_store_; - TransportDIB* damage_buffer_; + TransportDIB* current_damage_buffer_; + TransportDIB* pending_damage_buffer_; gfx::Rect plugin_rect_; // Bitmap for crashed plugin. Lazily initialized, non-owning pointer. SkBitmap* sad_guest_; bool guest_crashed_; - bool resize_pending_; scoped_ptr<BrowserPluginHostMsg_ResizeGuest_Params> pending_resize_params_; // True if we have ever sent a NavigateGuest message to the embedder. bool navigate_src_sent_; diff --git a/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/content/renderer/browser_plugin/browser_plugin_browsertest.cc index 4904da8..e59c2a5 100644 --- a/content/renderer/browser_plugin/browser_plugin_browsertest.cc +++ b/content/renderer/browser_plugin/browser_plugin_browsertest.cc @@ -120,8 +120,8 @@ int BrowserPluginTest::ExecuteScriptAndReturnInt( // This test verifies that an initial resize occurs when we instantiate the // browser plugin. This test also verifies that the browser plugin is waiting // for a BrowserPluginMsg_UpdateRect in response. We issue an UpdateRect, and -// we observe an UpdateRect_ACK, with the resize_pending_ reset, indiciating -// that the BrowserPlugin is not waiting for any more UpdateRects to +// we observe an UpdateRect_ACK, with the |pending_damage_buffer_| reset, +// indiciating that the BrowserPlugin is not waiting for any more UpdateRects to // satisfy its resize request. TEST_F(BrowserPluginTest, InitialResize) { LoadHTML(GetHTMLForBrowserPluginObject().c_str()); @@ -131,32 +131,33 @@ TEST_F(BrowserPluginTest, InitialResize) { browser_plugin_manager()->sink().GetUniqueMessageMatching( BrowserPluginHostMsg_ResizeGuest::ID); ASSERT_TRUE(msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); - BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; - ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); - int instance_id = resize_params.a; - BrowserPluginHostMsg_ResizeGuest_Params params(resize_params.b); - EXPECT_EQ(640, params.width); - EXPECT_EQ(480, params.height); - // Verify that the browser plugin wasn't already waiting on a resize when this - // resize happened. - EXPECT_FALSE(params.resize_pending); + int instance_id = -1; + BrowserPluginHostMsg_ResizeGuest_Params params; + BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, ¶ms); + EXPECT_EQ(640, params.view_size.width()); + EXPECT_EQ(480, params.view_size.height()); MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPlugin*>( browser_plugin_manager()->GetBrowserPlugin(instance_id)); ASSERT_TRUE(browser_plugin); // Now the browser plugin is expecting a UpdateRect resize. - EXPECT_TRUE(browser_plugin->resize_pending_); + EXPECT_TRUE(browser_plugin->pending_damage_buffer_); - // Send the BrowserPlugin an UpdateRect equal to its container size. - // That should clear the resize_pending_ flag. + // Send the BrowserPlugin an UpdateRect equal to its container size with + // the same damage buffer. That should clear |pending_damage_buffer_|. BrowserPluginMsg_UpdateRect_Params update_rect_params; + update_rect_params.damage_buffer_identifier = +#if defined(OS_MACOSX) + browser_plugin->pending_damage_buffer_->id(); +#else + browser_plugin->pending_damage_buffer_->handle(); +#endif update_rect_params.view_size = gfx::Size(640, 480); update_rect_params.scale_factor = 1.0f; update_rect_params.is_resize_ack = true; browser_plugin->UpdateRect(0, update_rect_params); - EXPECT_FALSE(browser_plugin->resize_pending_); + EXPECT_FALSE(browser_plugin->pending_damage_buffer_); } // Verify that the src attribute on the browser plugin works as expected. @@ -176,14 +177,9 @@ TEST_F(BrowserPluginTest, SrcAttribute) { BrowserPluginHostMsg_NavigateGuest::ID); ASSERT_TRUE(msg); - int instance_id; + int instance_id = -1; std::string src; - BrowserPluginHostMsg_ResizeGuest_Params resize_params; - BrowserPluginHostMsg_NavigateGuest::Read( - msg, - &instance_id, - &src, - &resize_params); + BrowserPluginHostMsg_NavigateGuest::Read(msg, &instance_id, &src); EXPECT_EQ("foo", src); } @@ -204,14 +200,9 @@ TEST_F(BrowserPluginTest, SrcAttribute) { BrowserPluginHostMsg_NavigateGuest::ID); ASSERT_TRUE(msg); - int instance_id; + int instance_id = -1; std::string src; - BrowserPluginHostMsg_ResizeGuest_Params resize_params; - BrowserPluginHostMsg_NavigateGuest::Read( - msg, - &instance_id, - &src, - &resize_params); + BrowserPluginHostMsg_NavigateGuest::Read(msg, &instance_id, &src); EXPECT_EQ("bar", src); std::string src_value = ExecuteScriptAndReturnString( @@ -222,6 +213,43 @@ TEST_F(BrowserPluginTest, SrcAttribute) { TEST_F(BrowserPluginTest, ResizeFlowControl) { LoadHTML(GetHTMLForBrowserPluginObject().c_str()); + int instance_id = -1; + { + // Ensure we get a NavigateGuest on the initial navigation and grab the + // BrowserPlugin's instance_id from there. + std::string src; + const IPC::Message* nav_msg = + browser_plugin_manager()->sink().GetUniqueMessageMatching( + BrowserPluginHostMsg_NavigateGuest::ID); + ASSERT_TRUE(nav_msg); + BrowserPluginHostMsg_NavigateGuest::Read(nav_msg, &instance_id, &src); + } + MockBrowserPlugin* browser_plugin = + static_cast<MockBrowserPlugin*>( + browser_plugin_manager()->GetBrowserPlugin(instance_id)); + ASSERT_TRUE(browser_plugin); + EXPECT_TRUE(browser_plugin->pending_damage_buffer_); + // Send an UpdateRect to the BrowserPlugin to make it use the pending damage + // buffer. + { + // We send a stale UpdateRect to the BrowserPlugin. + BrowserPluginMsg_UpdateRect_Params update_rect_params; + update_rect_params.view_size = gfx::Size(640, 480); + update_rect_params.scale_factor = 1.0f; + update_rect_params.is_resize_ack = true; + // By sending the damage buffer handle back to BrowserPlugin on UpdateRect, + // then the BrowserPlugin knows that the browser process has received and + // has begun to use the pending_damage_buffer. + update_rect_params.damage_buffer_identifier = +#if defined(OS_MACOSX) + browser_plugin->pending_damage_buffer_->id(); +#else + browser_plugin->pending_damage_buffer_->handle(); +#endif + browser_plugin->UpdateRect(0, update_rect_params); + EXPECT_EQ(NULL, browser_plugin->pending_damage_buffer_); + } + browser_plugin_manager()->sink().ClearMessages(); // Resize the browser plugin three times. @@ -232,50 +260,56 @@ TEST_F(BrowserPluginTest, ResizeFlowControl) { ExecuteJavaScript("document.getElementById('browserplugin').width = '643px'"); ProcessPendingMessages(); - // Expect to see three messsages in the sink. - EXPECT_EQ(3u, browser_plugin_manager()->sink().message_count()); + // Expect to see one 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()); const IPC::Message* msg = browser_plugin_manager()->sink().GetFirstMessageMatching( BrowserPluginHostMsg_ResizeGuest::ID); ASSERT_TRUE(msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); - BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; - ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); - int instance_id = resize_params.a; - BrowserPluginHostMsg_ResizeGuest_Params params(resize_params.b); - EXPECT_EQ(641, params.width); - EXPECT_EQ(480, params.height); + BrowserPluginHostMsg_ResizeGuest_Params params; + BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, ¶ms); + EXPECT_EQ(641, params.view_size.width()); + EXPECT_EQ(480, params.view_size.height()); // This indicates that the BrowserPlugin has sent out a previous resize // request but has not yet received an UpdateRect for that request. - // We send this resize regardless to update the damage buffer in the - // browser process, so it's ready when the guest sends the appropriate - // UpdateRect. - EXPECT_TRUE(params.resize_pending); + EXPECT_TRUE(browser_plugin->pending_damage_buffer_); - MockBrowserPlugin* browser_plugin = - static_cast<MockBrowserPlugin*>( - browser_plugin_manager()->GetBrowserPlugin(instance_id)); - ASSERT_TRUE(browser_plugin); { // We send a stale UpdateRect to the BrowserPlugin. BrowserPluginMsg_UpdateRect_Params update_rect_params; - update_rect_params.view_size = gfx::Size(640, 480); + update_rect_params.view_size = gfx::Size(641, 480); update_rect_params.scale_factor = 1.0f; update_rect_params.is_resize_ack = true; + update_rect_params.damage_buffer_identifier = +#if defined(OS_MACOSX) + browser_plugin->pending_damage_buffer_->id(); +#else + browser_plugin->pending_damage_buffer_->handle(); +#endif browser_plugin->UpdateRect(0, update_rect_params); // This tells us that the BrowserPlugin is still expecting another // UpdateRect with the most recent size. - EXPECT_TRUE(browser_plugin->resize_pending_); + EXPECT_TRUE(browser_plugin->pending_damage_buffer_); } + // Send the BrowserPlugin another UpdateRect, but this time with a size + // that matches the size of the container. { BrowserPluginMsg_UpdateRect_Params update_rect_params; update_rect_params.view_size = gfx::Size(643, 480); update_rect_params.scale_factor = 1.0f; update_rect_params.is_resize_ack = true; + update_rect_params.damage_buffer_identifier = +#if defined(OS_MACOSX) + browser_plugin->pending_damage_buffer_->id(); +#else + browser_plugin->pending_damage_buffer_->handle(); +#endif browser_plugin->UpdateRect(0, update_rect_params); // The BrowserPlugin has finally received an UpdateRect that satisifes // its current size, and so it is happy. - EXPECT_FALSE(browser_plugin->resize_pending_); + EXPECT_FALSE(browser_plugin->pending_damage_buffer_); } } @@ -287,10 +321,9 @@ TEST_F(BrowserPluginTest, GuestCrash) { browser_plugin_manager()->sink().GetFirstMessageMatching( BrowserPluginHostMsg_ResizeGuest::ID); ASSERT_TRUE(msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); - BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; - ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); - int instance_id = resize_params.a; + int instance_id = -1; + BrowserPluginHostMsg_ResizeGuest_Params params; + BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, ¶ms); MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPlugin*>( @@ -368,10 +401,9 @@ TEST_F(BrowserPluginTest, CustomEvents) { browser_plugin_manager()->sink().GetFirstMessageMatching( BrowserPluginHostMsg_ResizeGuest::ID); ASSERT_TRUE(msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); - BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; - ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); - int instance_id = resize_params.a; + int instance_id = -1; + BrowserPluginHostMsg_ResizeGuest_Params params; + BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, ¶ms); MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPlugin*>( @@ -531,7 +563,7 @@ TEST_F(BrowserPluginTest, ImmutableAttributesAfterNavigation) { BrowserPluginHostMsg_CreateGuest::ID); ASSERT_TRUE(create_msg); - int create_instance_id; + int create_instance_id = -1; BrowserPluginHostMsg_CreateGuest_Params params; BrowserPluginHostMsg_CreateGuest::Read( create_msg, @@ -545,14 +577,9 @@ TEST_F(BrowserPluginTest, ImmutableAttributesAfterNavigation) { BrowserPluginHostMsg_NavigateGuest::ID); ASSERT_TRUE(msg); - int instance_id; + int instance_id = -1; std::string src; - BrowserPluginHostMsg_ResizeGuest_Params resize_params; - BrowserPluginHostMsg_NavigateGuest::Read( - msg, - &instance_id, - &src, - &resize_params); + BrowserPluginHostMsg_NavigateGuest::Read(msg, &instance_id, &src); EXPECT_STREQ("bar", src.c_str()); EXPECT_EQ(create_instance_id, instance_id); } @@ -599,10 +626,9 @@ TEST_F(BrowserPluginTest, RemoveEventListenerInEventListener) { browser_plugin_manager()->sink().GetFirstMessageMatching( BrowserPluginHostMsg_ResizeGuest::ID); ASSERT_TRUE(msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); - BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; - ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); - int instance_id = resize_params.a; + int instance_id = -1; + BrowserPluginHostMsg_ResizeGuest_Params params; + BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, ¶ms); MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPlugin*>( @@ -655,10 +681,9 @@ TEST_F(BrowserPluginTest, MultipleEventListeners) { browser_plugin_manager()->sink().GetFirstMessageMatching( BrowserPluginHostMsg_ResizeGuest::ID); ASSERT_TRUE(msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); - BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; - ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); - int instance_id = resize_params.a; + int instance_id = -1; + BrowserPluginHostMsg_ResizeGuest_Params params; + BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, ¶ms); MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPlugin*>( @@ -683,10 +708,9 @@ TEST_F(BrowserPluginTest, RemoveBrowserPluginOnExit) { browser_plugin_manager()->sink().GetFirstMessageMatching( BrowserPluginHostMsg_ResizeGuest::ID); ASSERT_TRUE(msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); - BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; - ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); - int instance_id = resize_params.a; + int instance_id = -1; + BrowserPluginHostMsg_ResizeGuest_Params params; + BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, ¶ms); MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPlugin*>( @@ -728,6 +752,7 @@ TEST_F(BrowserPluginTest, AutoSizeAttributes) { const char* kDisableAutoSize = "document.getElementById('browserplugin').autoSize = false;"; + int instance_id = -1; // Set some autosize parameters before navigating then navigate. // Verify that the BrowserPluginHostMsg_CreateGuest message contains // the correct autosize parameters. @@ -739,33 +764,63 @@ TEST_F(BrowserPluginTest, AutoSizeAttributes) { BrowserPluginHostMsg_CreateGuest::ID); ASSERT_TRUE(create_msg); - int create_instance_id; BrowserPluginHostMsg_CreateGuest_Params params; BrowserPluginHostMsg_CreateGuest::Read( create_msg, - &create_instance_id, + &instance_id, ¶ms); - EXPECT_TRUE(params.auto_size.enable); - EXPECT_EQ(42, params.auto_size.min_size.width()); - EXPECT_EQ(43, params.auto_size.min_size.height()); - EXPECT_EQ(1337, params.auto_size.max_size.width()); - EXPECT_EQ(1338, params.auto_size.max_size.height()); + EXPECT_TRUE(params.auto_size_params.enable); + EXPECT_EQ(42, params.auto_size_params.min_size.width()); + EXPECT_EQ(43, params.auto_size_params.min_size.height()); + EXPECT_EQ(1337, params.auto_size_params.max_size.width()); + EXPECT_EQ(1338, params.auto_size_params.max_size.height()); } - // Disable autosize and verify that the BrowserPlugin issues a - // BrowserPluginHostMsg_SetAutoSize with the change. + // Verify that we are waiting for the browser process to grab the new + // damage buffer. + MockBrowserPlugin* browser_plugin = + static_cast<MockBrowserPlugin*>( + browser_plugin_manager()->GetBrowserPlugin(instance_id)); + EXPECT_TRUE(browser_plugin->pending_damage_buffer_); + // Disable autosize. AutoSize state will not be sent to the guest until + // the guest has responded to the last resize request. ExecuteJavaScript(kDisableAutoSize); ProcessPendingMessages(); + + const IPC::Message* auto_size_msg = + browser_plugin_manager()->sink().GetUniqueMessageMatching( + BrowserPluginHostMsg_SetAutoSize::ID); + EXPECT_FALSE(auto_size_msg); + + // Send the BrowserPlugin an UpdateRect equal to its |max_size| with + // the same damage buffer. + BrowserPluginMsg_UpdateRect_Params update_rect_params; + update_rect_params.damage_buffer_identifier = +#if defined(OS_MACOSX) + browser_plugin->pending_damage_buffer_->id(); +#else + browser_plugin->pending_damage_buffer_->handle(); +#endif + update_rect_params.view_size = gfx::Size(1337, 1338); + update_rect_params.scale_factor = 1.0f; + update_rect_params.is_resize_ack = true; + browser_plugin->UpdateRect(0, update_rect_params); + + // Verify that the autosize state has been updated. { const IPC::Message* auto_size_msg = browser_plugin_manager()->sink().GetUniqueMessageMatching( - BrowserPluginHostMsg_SetAutoSize::ID); + BrowserPluginHostMsg_UpdateRect_ACK::ID); ASSERT_TRUE(auto_size_msg); - PickleIterator iter = IPC::SyncMessage::GetDataIterator(auto_size_msg); - BrowserPluginHostMsg_SetAutoSize::SendParam set_auto_size_params; - ASSERT_TRUE(IPC::ReadParam(auto_size_msg, &iter, &set_auto_size_params)); - const BrowserPluginHostMsg_AutoSize_Params& auto_size_params = - set_auto_size_params.b; + int instance_id = -1; + int message_id = 0; + BrowserPluginHostMsg_AutoSize_Params auto_size_params; + BrowserPluginHostMsg_ResizeGuest_Params resize_params; + BrowserPluginHostMsg_UpdateRect_ACK::Read(auto_size_msg, + &instance_id, + &message_id, + &auto_size_params, + &resize_params); EXPECT_FALSE(auto_size_params.enable); EXPECT_EQ(42, auto_size_params.min_size.width()); EXPECT_EQ(43, auto_size_params.min_size.height()); diff --git a/content/renderer/browser_plugin/mock_browser_plugin.cc b/content/renderer/browser_plugin/mock_browser_plugin.cc index 2ea268f..dc9f545 100644 --- a/content/renderer/browser_plugin/mock_browser_plugin.cc +++ b/content/renderer/browser_plugin/mock_browser_plugin.cc @@ -22,10 +22,10 @@ TransportDIB* MockBrowserPlugin::CreateTransportDIB(const size_t size) { return TransportDIB::Create(size, transport_dib_next_sequence_number_++); } -void MockBrowserPlugin::FreeDamageBuffer() { - DCHECK(damage_buffer_); - RenderProcess::current()->FreeTransportDIB(damage_buffer_); - damage_buffer_ = NULL; +void MockBrowserPlugin::FreeDamageBuffer(TransportDIB** damage_buffer) { + DCHECK(*damage_buffer); + RenderProcess::current()->FreeTransportDIB(*damage_buffer); + *damage_buffer = NULL; } } // namespace content diff --git a/content/renderer/browser_plugin/mock_browser_plugin.h b/content/renderer/browser_plugin/mock_browser_plugin.h index 5e00d89..965b7dd 100644 --- a/content/renderer/browser_plugin/mock_browser_plugin.h +++ b/content/renderer/browser_plugin/mock_browser_plugin.h @@ -20,11 +20,11 @@ class MockBrowserPlugin : public BrowserPlugin { virtual ~MockBrowserPlugin(); virtual TransportDIB* CreateTransportDIB(const size_t size) OVERRIDE; - virtual void FreeDamageBuffer() OVERRIDE; + virtual void FreeDamageBuffer(TransportDIB** damage_buffer) OVERRIDE; // Allow poking at a few private members. using BrowserPlugin::guest_crashed_; - using BrowserPlugin::resize_pending_; + using BrowserPlugin::pending_damage_buffer_; private: int transport_dib_next_sequence_number_; |