Index: content/renderer/browser_plugin/browser_plugin.cc |
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc |
index 8ba5421f33aa700fe63e733024d9a5185ed74684..fe3ff38f252a3087254fcd66393b179e4bba6a0b 100644 |
--- a/content/renderer/browser_plugin/browser_plugin.cc |
+++ b/content/renderer/browser_plugin/browser_plugin.cc |
@@ -6,6 +6,9 @@ |
#include "base/message_loop.h" |
#include "base/string_util.h" |
+#if defined (OS_WIN) |
+#include "base/sys_info.h" |
+#endif |
#include "content/common/browser_plugin_messages.h" |
#include "content/public/common/content_client.h" |
#include "content/public/renderer/content_renderer_client.h" |
@@ -54,6 +57,7 @@ BrowserPlugin::BrowserPlugin( |
sad_guest_(NULL), |
guest_crashed_(false), |
resize_pending_(false), |
+ navigate_src_sent_(false), |
parent_frame_(frame->identifier()) { |
BrowserPluginManager::Get()->AddBrowserPlugin(instance_id, this); |
bindings_.reset(new BrowserPluginBindings(this)); |
@@ -90,13 +94,21 @@ std::string BrowserPlugin::GetSrcAttribute() const { |
void BrowserPlugin::SetSrcAttribute(const std::string& src) { |
if (src == src_ && !guest_crashed_) |
return; |
- if (!src.empty()) { |
+ if (!src.empty() || navigate_src_sent_) { |
BrowserPluginManager::Get()->Send( |
- new BrowserPluginHostMsg_NavigateOrCreateGuest( |
+ new BrowserPluginHostMsg_NavigateGuest( |
render_view_->GetRoutingID(), |
instance_id_, |
parent_frame_, |
- src)); |
+ src, |
+ gfx::Size(width(), height()))); |
+ // Record that we sent a NavigateGuest message to embedder. Once we send |
+ // such a message, subsequent SetSrcAttribute() calls must always send |
+ // NavigateGuest messages to the embedder (even if |src| is empty), so |
+ // resize works correctly for all cases (e.g. The embedder can reset the |
+ // guest's |src| to empty value, resize and then set the |src| to a |
+ // non-empty value). |
+ navigate_src_sent_ = true; |
} |
src_ = src; |
guest_crashed_ = false; |
@@ -310,8 +322,9 @@ void BrowserPlugin::paint(WebCanvas* canvas, const WebRect& rect) { |
paint.setStyle(SkPaint::kFill_Style); |
paint.setColor(SK_ColorWHITE); |
canvas->drawRect(image_data_rect, paint); |
- // Stay at white if we have no src set, or we don't yet have a backing store. |
- if (!backing_store_.get() || src_.empty()) |
+ // Stay at white if we have never set a non-empty src, or we don't yet have a |
+ // backing store. |
+ if (!backing_store_.get() || !navigate_src_sent_) |
return; |
float inverse_scale_factor = 1.0f / backing_store_->GetScaleFactor(); |
canvas->scale(inverse_scale_factor, inverse_scale_factor); |
@@ -327,23 +340,51 @@ void BrowserPlugin::updateGeometry( |
int old_height = height(); |
plugin_rect_ = window_rect; |
if (old_width == window_rect.width && |
- old_height == window_rect.height) |
+ old_height == window_rect.height) { |
+ return; |
+ } |
+ // 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 can return immediately. |
+ if (!navigate_src_sent_) |
return; |
const size_t stride = skia::PlatformCanvas::StrideForWidth(window_rect.width); |
- const size_t size = window_rect.height * |
- stride * |
- GetDeviceScaleFactor() * |
- GetDeviceScaleFactor(); |
+ // 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>(window_rect.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 = |
- RenderProcess::current()->CreateTransportDIB(size); |
- DCHECK(new_damage_buffer); |
+ TransportDIB* new_damage_buffer = NULL; |
+#if defined(OS_WIN) |
+ size_t allocation_granularity = base::SysInfo::VMAllocationGranularity(); |
+ size_t shared_mem_size = size / allocation_granularity + 1; |
+ shared_mem_size = shared_mem_size * allocation_granularity; |
+ |
+ base::SharedMemory shared_mem; |
+ if (!shared_mem.CreateAnonymous(shared_mem_size)) |
+ NOTREACHED() << "Unable to create shared memory of size:" << size; |
+ new_damage_buffer = TransportDIB::Map(shared_mem.handle()); |
+#else |
+ new_damage_buffer = RenderProcess::current()->CreateTransportDIB(size); |
+#endif |
+ if (!new_damage_buffer) |
+ NOTREACHED() << "Unable to create damage buffer"; |
+ DCHECK(new_damage_buffer->memory()); |
+ // Insert the magic word. |
+ *static_cast<unsigned int*>(new_damage_buffer->memory()) = 0xdeadbeef; |
BrowserPluginHostMsg_ResizeGuest_Params params; |
params.damage_buffer_id = new_damage_buffer->id(); |
+#if defined(OS_WIN) |
+ params.damage_buffer_size = size; |
+#endif |
params.width = window_rect.width; |
params.height = window_rect.height; |
params.resize_pending = resize_pending_; |
@@ -377,7 +418,7 @@ bool BrowserPlugin::acceptsInputEvents() { |
bool BrowserPlugin::handleInputEvent(const WebKit::WebInputEvent& event, |
WebKit::WebCursorInfo& cursor_info) { |
- if (guest_crashed_ || src_.empty()) |
+ if (guest_crashed_ || !navigate_src_sent_) |
return false; |
bool handled = false; |
WebCursor cursor; |