| 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 91257e879ba4015f7cb65844b57b8e4a0fbf19fe..0e75552aa1b44e4c909035c82c030267a59e4480 100644
|
| --- a/content/renderer/browser_plugin/browser_plugin.cc
|
| +++ b/content/renderer/browser_plugin/browser_plugin.cc
|
| @@ -50,10 +50,15 @@ const char kLoadRedirectEventName[] = "loadredirect";
|
| const char kLoadStartEventName[] = "loadstart";
|
| const char kLoadStopEventName[] = "loadstop";
|
| const char kNewURL[] = "newUrl";
|
| +const char kNewHeight[] = "newHeight";
|
| +const char kNewWidth[] = "newWidth";
|
| const char kOldURL[] = "oldUrl";
|
| +const char kOldHeight[] = "oldHeight";
|
| +const char kOldWidth[] = "oldWidth";
|
| const char kPartitionAttribute[] = "partition";
|
| const char kPersistPrefix[] = "persist:";
|
| const char kProcessId[] = "processId";
|
| +const char kSizeChangedEventName[] = "sizechanged";
|
| const char kSrcAttribute[] = "src";
|
| const char kType[] = "type";
|
| const char kURL[] = "url";
|
| @@ -101,6 +106,7 @@ BrowserPlugin::BrowserPlugin(
|
| plugin_focused_(false),
|
| embedder_focused_(false),
|
| visible_(true),
|
| + size_changed_in_flight_(false),
|
| current_nav_entry_index_(0),
|
| nav_entry_count_(0) {
|
| BrowserPluginManager::Get()->AddBrowserPlugin(instance_id, this);
|
| @@ -169,27 +175,77 @@ void BrowserPlugin::SetAutoSizeAttribute(bool auto_size) {
|
| if (auto_size_ == auto_size)
|
| return;
|
| auto_size_ = auto_size;
|
| + last_view_size_ = plugin_rect_.size();
|
| UpdateGuestAutoSizeState();
|
| }
|
|
|
| void BrowserPlugin::PopulateAutoSizeParameters(
|
| - BrowserPluginHostMsg_AutoSize_Params* params) const {
|
| + BrowserPluginHostMsg_AutoSize_Params* params) {
|
| + // If maxWidth or maxHeight have not been set, set them to the container size.
|
| + max_height_ = max_height_ ? max_height_ : height();
|
| + max_width_ = max_width_ ? max_width_ : width();
|
| + // minWidth should not be bigger than maxWidth, and minHeight should not be
|
| + // bigger than maxHeight.
|
| + min_height_ = std::min(min_height_, max_height_);
|
| + min_width_ = std::min(min_width_, max_width_);
|
| params->enable = auto_size_;
|
| - params->max_height = max_height_;
|
| - params->max_width = max_width_;
|
| - params->min_height = min_height_;
|
| - params->min_width = min_width_;
|
| + params->max_size = gfx::Size(max_width_, max_height_);
|
| + params->min_size = gfx::Size(min_width_, min_height_);
|
| }
|
|
|
| -void BrowserPlugin::UpdateGuestAutoSizeState() const {
|
| +void BrowserPlugin::UpdateGuestAutoSizeState() {
|
| if (!navigate_src_sent_)
|
| return;
|
| - BrowserPluginHostMsg_AutoSize_Params params;
|
| - PopulateAutoSizeParameters(¶ms);
|
| + 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);
|
| BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_SetAutoSize(
|
| render_view_routing_id_,
|
| instance_id_,
|
| - params));
|
| + auto_size_params,
|
| + resize_params));
|
| + if (damage_buffer_)
|
| + FreeDamageBuffer();
|
| + damage_buffer_ = new_damage_buffer;
|
| +}
|
| +
|
| +void BrowserPlugin::SizeChangedDueToAutoSize(const gfx::Size& old_view_size) {
|
| + size_changed_in_flight_ = false;
|
| + if (!HasListeners(kSizeChangedEventName))
|
| + return;
|
| +
|
| + WebKit::WebElement plugin = container()->element();
|
| + v8::HandleScope handle_scope;
|
| + v8::Context::Scope context_scope(
|
| + plugin.document().frame()->mainWorldScriptContext());
|
| +
|
| + // Construct the sizechanged event object.
|
| + v8::Local<v8::Object> event = v8::Object::New();
|
| + event->Set(v8::String::New(kOldHeight, sizeof(kOldHeight) - 1),
|
| + v8::Integer::New(old_view_size.height()),
|
| + v8::ReadOnly);
|
| + event->Set(v8::String::New(kOldWidth, sizeof(kOldWidth) - 1),
|
| + v8::Integer::New(old_view_size.width()),
|
| + v8::ReadOnly);
|
| + event->Set(v8::String::New(kNewHeight, sizeof(kNewHeight) - 1),
|
| + v8::Integer::New(last_view_size_.height()),
|
| + v8::ReadOnly);
|
| + event->Set(v8::String::New(kNewWidth, sizeof(kNewWidth) - 1),
|
| + v8::Integer::New(last_view_size_.width()),
|
| + v8::ReadOnly);
|
| + TriggerEvent(kSizeChangedEventName, &event);
|
| }
|
|
|
| void BrowserPlugin::SetMaxHeightAttribute(int max_height) {
|
| @@ -228,6 +284,10 @@ void BrowserPlugin::SetMinWidthAttribute(int min_width) {
|
| UpdateGuestAutoSizeState();
|
| }
|
|
|
| +bool BrowserPlugin::InAutoSizeBounds(const gfx::Size& size) const {
|
| + return size.width() <= max_width_ && size.height() <= max_height_;
|
| +}
|
| +
|
| NPObject* BrowserPlugin::GetContentWindow() const {
|
| if (content_window_routing_id_ == MSG_ROUTING_NONE)
|
| return NULL;
|
| @@ -321,6 +381,7 @@ void BrowserPlugin::InitializeEvents() {
|
| event_listener_map_[kLoadRedirectEventName] = EventListeners();
|
| event_listener_map_[kLoadStartEventName] = EventListeners();
|
| event_listener_map_[kLoadStopEventName] = EventListeners();
|
| + event_listener_map_[kSizeChangedEventName] = EventListeners();
|
| }
|
|
|
| void BrowserPlugin::RemoveEventListeners() {
|
| @@ -428,8 +489,10 @@ void BrowserPlugin::Reload() {
|
| void BrowserPlugin::UpdateRect(
|
| int message_id,
|
| const BrowserPluginMsg_UpdateRect_Params& params) {
|
| - if (width() != params.view_size.width() ||
|
| - height() != params.view_size.height()) {
|
| + if ((!auto_size_ &&
|
| + (width() != params.view_size.width() ||
|
| + height() != params.view_size.height())) ||
|
| + (auto_size_ && (!InAutoSizeBounds(params.view_size)))) {
|
| BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_UpdateRect_ACK(
|
| render_view_routing_id_,
|
| instance_id_,
|
| @@ -437,16 +500,44 @@ void BrowserPlugin::UpdateRect(
|
| gfx::Size(width(), height())));
|
| 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);
|
| + gfx::Size old_view_size = last_view_size_;
|
| + last_view_size_ = params.view_size;
|
| + // Schedule a SizeChanged instead of calling it directly to ensure that
|
| + // the backing store has been updated before the developer attempts to
|
| + // 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
|
| + // |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_) {
|
| + size_changed_in_flight_ = true;
|
| + MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&BrowserPlugin::SizeChangedDueToAutoSize,
|
| + base::Unretained(this),
|
| + old_view_size));
|
| + }
|
| + }
|
|
|
| float backing_store_scale_factor =
|
| backing_store_.get() ? backing_store_->GetScaleFactor() : 1.0f;
|
|
|
| - if (params.is_resize_ack ||
|
| - backing_store_scale_factor != params.scale_factor) {
|
| + 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()) {
|
| + 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(width(), height()),
|
| - params.scale_factor));
|
| + new BrowserPluginBackingStore(
|
| + gfx::Size(backing_store_width, backing_store_height),
|
| + params.scale_factor));
|
| }
|
|
|
| // Update the backing store.
|
| @@ -778,41 +869,17 @@ void BrowserPlugin::updateGeometry(
|
| int old_height = height();
|
| plugin_rect_ = window_rect;
|
| if (auto_size_ || (old_width == window_rect.width &&
|
| - old_height == window_rect.height)) {
|
| + old_height == window_rect.height)) {
|
| return;
|
| }
|
| -
|
| - const size_t stride = skia::PlatformCanvas::StrideForWidth(window_rect.width);
|
| - // Make sure the size of the damage buffer is at least four bytes so that we
|
| - // can fit in a magic word to verify that the memory is shared correctly.
|
| - size_t size =
|
| - std::max(sizeof(unsigned int),
|
| - static_cast<size_t>(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 = CreateTransportDIB(size);
|
| pending_resize_params_.reset();
|
|
|
| scoped_ptr<BrowserPluginHostMsg_ResizeGuest_Params> params(
|
| new BrowserPluginHostMsg_ResizeGuest_Params);
|
| - params->damage_buffer_id = new_damage_buffer->id();
|
| -#if defined(OS_MACOSX)
|
| - // |damage_buffer_id| is not enough to retrieve the damage buffer (on browser
|
| - // side) since we don't let the browser cache the damage buffer. We need a
|
| - // handle to the damage buffer for this.
|
| - params->damage_buffer_handle = new_damage_buffer->handle();
|
| -#endif
|
| -#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_;
|
| - params->scale_factor = GetDeviceScaleFactor();
|
| +
|
| + TransportDIB* new_damage_buffer =
|
| + PopulateResizeGuestParameters(params.get(), width(), height());
|
| + DCHECK(new_damage_buffer);
|
|
|
| if (navigate_src_sent_) {
|
| BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ResizeGuest(
|
| @@ -845,6 +912,39 @@ void BrowserPlugin::FreeDamageBuffer() {
|
| #endif
|
| }
|
|
|
| +TransportDIB* BrowserPlugin::PopulateResizeGuestParameters(
|
| + BrowserPluginHostMsg_ResizeGuest_Params* params,
|
| + int view_width, int view_height) {
|
| + const size_t stride = skia::PlatformCanvas::StrideForWidth(view_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 *
|
| + 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)
|
| + // |damage_buffer_id| is not enough to retrieve the damage buffer (on browser
|
| + // side) since we don't let the browser cache the damage buffer. We need a
|
| + // handle to the damage buffer for this.
|
| + params->damage_buffer_handle = new_damage_buffer->handle();
|
| +#endif
|
| +#if defined(OS_WIN)
|
| + params->damage_buffer_size = size;
|
| +#endif
|
| + params->width = view_width;
|
| + params->height = view_height;
|
| + params->resize_pending = resize_pending_;
|
| + params->scale_factor = GetDeviceScaleFactor();
|
| + return new_damage_buffer;
|
| +}
|
| +
|
| BrowserPluginHostMsg_ResizeGuest_Params*
|
| BrowserPlugin::GetPendingResizeParams() {
|
| if (pending_resize_params_.get()) {
|
|
|