diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 1358d41822d..f82a65818a6 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -44,12 +44,40 @@ #include "atom/common/node_includes.h" +namespace mate { + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + atom::api::SetSizeParams* out) { + mate::Dictionary params; + if (!ConvertFromV8(isolate, val, ¶ms)) + return false; + bool autosize; + if (params.Get("enableAutoSize", &autosize)) + out->enable_auto_size.reset(new bool(true)); + gfx::Size size; + if (params.Get("min", &size)) + out->min_size.reset(new gfx::Size(size)); + if (params.Get("max", &size)) + out->max_size.reset(new gfx::Size(size)); + return true; + } +}; + +} // namespace mate + + namespace atom { namespace api { namespace { +const int kDefaultWidth = 300; +const int kDefaultHeight = 300; + v8::Persistent template_; // Get the window that has the |guest| embedded. @@ -85,7 +113,8 @@ WebContents::WebContents(content::WebContents* web_contents) element_instance_id_(-1), guest_opaque_(true), guest_host_(nullptr), - auto_size_enabled_(false) { + auto_size_enabled_(false), + is_full_page_plugin_(false) { } WebContents::WebContents(const mate::Dictionary& options) @@ -93,7 +122,8 @@ WebContents::WebContents(const mate::Dictionary& options) element_instance_id_(-1), guest_opaque_(true), guest_host_(nullptr), - auto_size_enabled_(false) { + auto_size_enabled_(false), + is_full_page_plugin_(false) { options.Get("guestInstanceId", &guest_instance_id_); auto browser_context = AtomBrowserContext::Get(); @@ -612,31 +642,57 @@ bool WebContents::SendIPCMessage(const base::string16& channel, return Send(new AtomViewMsg_Message(routing_id(), channel, args)); } -void WebContents::SetAutoSize(bool enabled, - const gfx::Size& min_size, - const gfx::Size& max_size) { +void WebContents::SetSize(const SetSizeParams& params) { + bool enable_auto_size = + params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_; + gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_; + gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_; + + if (params.normal_size) + normal_size_ = *params.normal_size; + min_auto_size_ = min_size; min_auto_size_.SetToMin(max_size); max_auto_size_ = max_size; max_auto_size_.SetToMax(min_size); - enabled &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty(); - if (!enabled && !auto_size_enabled_) - return; - - auto_size_enabled_ = enabled; - - if (!attached()) - return; + enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty(); content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); - if (auto_size_enabled_) { + if (enable_auto_size) { + // Autosize is being enabled. rvh->EnableAutoResize(min_auto_size_, max_auto_size_); + normal_size_.SetSize(0, 0); } else { - rvh->DisableAutoResize(element_size_); - guest_size_ = element_size_; - GuestSizeChangedDueToAutoSize(guest_size_, element_size_); + // Autosize is being disabled. + // Use default width/height if missing from partially defined normal size. + if (normal_size_.width() && !normal_size_.height()) + normal_size_.set_height(GetDefaultSize().height()); + if (!normal_size_.width() && normal_size_.height()) + normal_size_.set_width(GetDefaultSize().width()); + + gfx::Size new_size; + if (!normal_size_.IsEmpty()) { + new_size = normal_size_; + } else if (!guest_size_.IsEmpty()) { + new_size = guest_size_; + } else { + new_size = GetDefaultSize(); + } + + if (auto_size_enabled_) { + // Autosize was previously enabled. + rvh->DisableAutoResize(new_size); + GuestSizeChangedDueToAutoSize(guest_size_, new_size); + } else { + // Autosize was already disabled. + guest_host_->SizeContents(new_size); + } + + guest_size_ = new_size; } + + auto_size_enabled_ = enable_auto_size; } void WebContents::SetAllowTransparency(bool allow) { @@ -727,7 +783,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("replace", &WebContents::Replace) .SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling) .SetMethod("_send", &WebContents::SendIPCMessage) - .SetMethod("setAutoSize", &WebContents::SetAutoSize) + .SetMethod("setSize", &WebContents::SetSize) .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) .SetMethod("isGuest", &WebContents::is_guest) .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) @@ -760,6 +816,16 @@ void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, new_size.width(), new_size.height()); } +gfx::Size WebContents::GetDefaultSize() const { + if (is_full_page_plugin_) { + // Full page plugins default to the size of the owner's viewport. + return embedder_web_contents_->GetRenderWidgetHostView() + ->GetVisibleViewportSize(); + } else { + return gfx::Size(kDefaultWidth, kDefaultHeight); + } +} + // static mate::Handle WebContents::CreateFrom( v8::Isolate* isolate, content::WebContents* web_contents) { diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index c7a8bbbfc04..63248fd02a2 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -33,6 +33,22 @@ class WebDialogHelper; namespace api { +// A struct of parameters for SetSize(). The parameters are all declared as +// scoped pointers since they are all optional. Null pointers indicate that the +// parameter has not been provided, and the last used value should be used. Note +// that when |enable_auto_size| is true, providing |normal_size| is not +// meaningful. This is because the normal size of the guestview is overridden +// whenever autosizing occurs. +struct SetSizeParams { + SetSizeParams() {} + ~SetSizeParams() {} + + scoped_ptr enable_auto_size; + scoped_ptr min_size; + scoped_ptr max_size; + scoped_ptr normal_size; +}; + class WebContents : public mate::EventEmitter, public content::BrowserPluginGuestDelegate, public content::WebContentsDelegate, @@ -89,10 +105,9 @@ class WebContents : public mate::EventEmitter, bool SendIPCMessage(const base::string16& channel, const base::ListValue& args); - // Toggles autosize mode for corresponding . - void SetAutoSize(bool enabled, - const gfx::Size& min_size, - const gfx::Size& max_size); + // Used to toggle autosize mode for this GuestView, and set both the automatic + // and normal sizes. + void SetSize(const SetSizeParams& params); // Sets the transparency of the guest. void SetAllowTransparency(bool allow); @@ -217,9 +232,17 @@ class WebContents : public mate::EventEmitter, const base::ListValue& args, IPC::Message* message); + // This method is invoked when the contents auto-resized to give the container + // an opportunity to match it if it wishes. + // + // This gives the derived class an opportunity to inform its container element + // or perform other actions. void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, const gfx::Size& new_size); + // Returns the default size of the guestview. + gfx::Size GetDefaultSize() const; + scoped_ptr web_dialog_helper_; scoped_ptr dialog_manager_; @@ -258,6 +281,12 @@ class WebContents : public mate::EventEmitter, // The minimum size constraints of the container element in autosize mode. gfx::Size min_auto_size_; + // The size that will be used when autosize mode is disabled. + gfx::Size normal_size_; + + // Whether the guest view is inside a plugin document. + bool is_full_page_plugin_; + DISALLOW_COPY_AND_ASSIGN(WebContents); }; diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index f0d2a89318d..e59bdb42c00 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -60,7 +60,7 @@ createGuest = (embedder, params) -> @viewInstanceId = params.instanceId min = width: params.minwidth, height: params.minheight max = width: params.maxwidth, height: params.maxheight - @setAutoSize params.autosize, min, max + @setSize params.autosize, min, max if params.src opts = {} @@ -132,8 +132,8 @@ ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) -> destroyGuest event.sender, id -ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, id, params) -> - guestInstances[id]?.guest.setAutoSize params.enableAutoSize, params.min, params.max +ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) -> + guestInstances[id]?.guest.setSize params ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) -> guestInstances[id]?.guest.setAllowTransparency allowtransparency diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index 4d5f599b352..2abc47edffe 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -67,8 +67,8 @@ module.exports = destroyGuest: (guestInstanceId) -> ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId - setAutoSize: (guestInstanceId, params) -> - ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', guestInstanceId, params + setSize: (guestInstanceId, params) -> + ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params setAllowTransparency: (guestInstanceId, allowtransparency) -> ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', guestInstanceId, allowtransparency diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index 51dd2475a4e..d2ea629f50d 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -72,7 +72,7 @@ class AutosizeDimensionAttribute extends WebViewAttribute handleMutation: (oldValue, newValue) -> return unless @webViewImpl.guestInstanceId - guestViewInternal.setAutoSize @webViewImpl.guestInstanceId, + guestViewInternal.setSize @webViewImpl.guestInstanceId, enableAutoSize: @webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() min: width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index a4edc58a10f..94cd897d6a3 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -107,6 +107,9 @@ class WebViewImpl minWidth = @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width minHeight = @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width + minWidth = Math.min minWidth, maxWidth + minHeight = Math.min minHeight, maxHeight + if not @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() or (newWidth >= minWidth and newWidth <= maxWidth and