Chromium Code Reviews| Index: chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm |
| diff --git a/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm b/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm |
| index 220299f6aa7e8884d1e398de16523749443517aa..419d9c70528991f4588161977297b08459b11218 100644 |
| --- a/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm |
| +++ b/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm |
| @@ -10,7 +10,10 @@ |
| #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h" |
| #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h" |
| #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_web_dialog_sheet.h" |
| +#include "chrome/browser/ui/webui/chrome_web_contents_handler.h" |
| +#include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_contents_observer.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/web_dialogs/web_dialog_delegate.h" |
| #include "ui/web_dialogs/web_dialog_ui.h" |
| @@ -22,19 +25,72 @@ using ui::WebDialogWebContentsDelegate; |
| namespace { |
| +class ConstrainedWebDialogDelegateMac; |
| + |
| +// WebContentsObserver that tracks the lifetime of the WebContents to avoid |
| +// potential use after destruction. |
| +class InitiatorWebContentsObserver |
|
erikchen
2015/11/11 21:22:30
What's the point of this class? Why not just use W
apacible
2015/11/12 02:02:24
Removed.
|
| + : public content::WebContentsObserver { |
| + public: |
| + explicit InitiatorWebContentsObserver(content::WebContents* web_contents) |
| + : content::WebContentsObserver(web_contents) { |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(InitiatorWebContentsObserver); |
| +}; |
| + |
| +class WebDialogWebContentsDelegateMac |
|
erikchen
2015/11/11 21:22:30
Provide a comment indicating the purpose of this c
apacible
2015/11/12 02:02:24
Done.
|
| + : public ui::WebDialogWebContentsDelegate { |
| + public: |
| + WebDialogWebContentsDelegateMac(content::BrowserContext* browser_context, |
| + InitiatorWebContentsObserver* observer, |
| + ConstrainedWebDialogDelegateBase* delegate) |
| + : ui::WebDialogWebContentsDelegate(browser_context, |
| + new ChromeWebContentsHandler()), |
| + initiator_observer_(observer), |
| + delegate_(delegate) { |
| + } |
| + ~WebDialogWebContentsDelegateMac() override {} |
| + |
| + void ResizeDueToAutoResize(content::WebContents* source, |
| + const gfx::Size& preferred_size) override { |
| + if (!initiator_observer_->web_contents()) |
| + return; |
| + delegate_->ResizeToGivenSize(preferred_size); |
| + } |
| + |
| + private: |
| + // weak, owned by ConstrainedWebDialogDelegateViewMac. |
| + InitiatorWebContentsObserver* const initiator_observer_; |
| + ConstrainedWebDialogDelegateBase* delegate_; // weak, owns us. |
|
erikchen
2015/11/11 21:22:30
"us" is ambiguous. For both this member, and the o
apacible
2015/11/12 02:02:24
Done.
|
| + |
| + DISALLOW_COPY_AND_ASSIGN(WebDialogWebContentsDelegateMac); |
| +}; |
| + |
| class ConstrainedWebDialogDelegateMac |
| : public ConstrainedWebDialogDelegateBase { |
| public: |
| ConstrainedWebDialogDelegateMac( |
| content::BrowserContext* browser_context, |
| - WebDialogDelegate* delegate) |
| - : ConstrainedWebDialogDelegateBase(browser_context, delegate, NULL) {} |
| + WebDialogDelegate* delegate, |
| + InitiatorWebContentsObserver* observer) |
| + : ConstrainedWebDialogDelegateBase(browser_context, delegate, |
| + new WebDialogWebContentsDelegateMac(browser_context, observer, |
|
erikchen
2015/11/11 21:22:30
Can you add a comment to the constructor of Constr
apacible
2015/11/12 02:02:23
Done.
|
| + this)) {} |
| // WebDialogWebContentsDelegate interface. |
| void CloseContents(WebContents* source) override { |
| window_->CloseWebContentsModalDialog(); |
| } |
| + // ConstrainedWebDialogDelegateBase: |
| + void ResizeToGivenSize(const gfx::Size size) override { |
| + NSSize updated_preferred_size = NSMakeSize(size.width(), |
| + size.height()); |
| + [window_->sheet() ResizeWithNewSize:updated_preferred_size]; |
| + } |
| + |
| void set_window(ConstrainedWindowMac* window) { window_ = window; } |
| ConstrainedWindowMac* window() const { return window_; } |
| @@ -49,13 +105,16 @@ class ConstrainedWebDialogDelegateMac |
| class ConstrainedWebDialogDelegateViewMac : |
| public ConstrainedWindowMacDelegate, |
| - public ConstrainedWebDialogDelegate { |
| + public ConstrainedWebDialogDelegate, |
| + public content::WebContentsObserver { |
| public: |
| ConstrainedWebDialogDelegateViewMac( |
| content::BrowserContext* browser_context, |
| WebDialogDelegate* delegate, |
| - content::WebContents* web_contents); |
| + content::WebContents* web_contents, |
| + const gfx::Size& min_size, |
| + const gfx::Size& max_size); |
| ~ConstrainedWebDialogDelegateViewMac() override {} |
| // ConstrainedWebDialogDelegate interface |
| @@ -74,16 +133,36 @@ class ConstrainedWebDialogDelegateViewMac : |
| gfx::NativeWindow GetNativeDialog() override { return window_; } |
| WebContents* GetWebContents() override { return impl_->GetWebContents(); } |
| gfx::Size GetMinimumSize() const override { |
| - NOTIMPLEMENTED(); |
| - return gfx::Size(); |
| + return min_size_; |
| } |
| gfx::Size GetMaximumSize() const override { |
| - NOTIMPLEMENTED(); |
| - return gfx::Size(); |
| + return max_size_; |
| } |
| gfx::Size GetPreferredSize() const override { |
| - NOTIMPLEMENTED(); |
| - return gfx::Size(); |
| + gfx::Size size; |
|
erikchen
2015/11/11 21:22:30
What does it mean for the preferred size to be 0,0
apacible
2015/11/12 02:02:23
Done.
|
| + if (!impl_->closed_via_webui()) { |
| + NSRect frame = [window_ frame]; |
| + size = gfx::Size(frame.size.width, frame.size.height); |
| + } |
| + return size; |
| + } |
| + |
| + // content::WebContentsObserver: |
| + void RenderViewCreated(content::RenderViewHost* render_view_host) override { |
| + if (!max_size_.IsEmpty()) |
| + EnableAutoResize(); |
| + } |
| + void RenderViewHostChanged(content::RenderViewHost* old_host, |
| + content::RenderViewHost* new_host) override { |
| + if (!max_size_.IsEmpty()) |
|
erikchen
2015/11/11 21:22:30
Shouldn't this conditional, and the other ones in
apacible
2015/11/12 02:02:23
These should actually all be DCHECK as they're all
apacible
2015/11/13 00:04:00
Updating this - Since ConstrainedWebDialogDelegate
|
| + EnableAutoResize(); |
| + } |
| + void DocumentOnLoadCompletedInMainFrame() override { |
| + if (!max_size_.IsEmpty()) { |
| + EnableAutoResize(); |
| + if (initiator_observer_.web_contents()) |
| + ShowDialog(); |
| + } |
| } |
| // ConstrainedWindowMacDelegate interface |
| @@ -93,26 +172,50 @@ class ConstrainedWebDialogDelegateViewMac : |
| delete this; |
| } |
| + void ShowDialog() { |
| + constrained_window_->ShowDialog(); |
| + } |
| + |
| private: |
| + void EnableAutoResize() { |
| + content::RenderViewHost* render_view_host = |
|
erikchen
2015/11/11 21:22:30
This relies on the assumption that GetWebContents(
apacible
2015/11/12 02:02:24
Done.
|
| + GetWebContents()->GetRenderViewHost(); |
| + render_view_host->EnableAutoResize(min_size_, max_size_); |
| + } |
| + |
| + InitiatorWebContentsObserver initiator_observer_; |
| scoped_ptr<ConstrainedWebDialogDelegateMac> impl_; |
| scoped_ptr<ConstrainedWindowMac> constrained_window_; |
| base::scoped_nsobject<NSWindow> window_; |
| + // Minimum and maximum sizes to determine dialog bounds for auto-resizing. |
| + const gfx::Size min_size_; |
| + const gfx::Size max_size_; |
|
erikchen
2015/11/11 21:22:30
It looks like this object has two internal states:
apacible
2015/11/12 02:02:23
Done.
|
| + |
| DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateViewMac); |
| }; |
| ConstrainedWebDialogDelegateViewMac::ConstrainedWebDialogDelegateViewMac( |
| content::BrowserContext* browser_context, |
| WebDialogDelegate* delegate, |
| - content::WebContents* web_contents) |
| - : impl_(new ConstrainedWebDialogDelegateMac(browser_context, delegate)) { |
| + content::WebContents* web_contents, |
| + const gfx::Size& min_size, |
| + const gfx::Size& max_size) |
| + : initiator_observer_(web_contents), |
| + impl_(new ConstrainedWebDialogDelegateMac(browser_context, delegate, |
| + &initiator_observer_)), |
| + min_size_(min_size), |
| + max_size_(max_size) { |
| + if (!max_size_.IsEmpty()) |
| + Observe(GetWebContents()); |
| + |
| // Create a window to hold web_contents in the constrained sheet: |
| gfx::Size size; |
| delegate->GetDialogSize(&size); |
| NSRect frame = NSMakeRect(0, 0, size.width(), size.height()); |
| - window_.reset( |
| - [[ConstrainedWindowCustomWindow alloc] initWithContentRect:frame]); |
| + window_.reset([[ConstrainedWindowCustomWindow alloc] |
| + initWithContentRect:frame]); |
| [GetWebContents()->GetNativeView() setFrame:frame]; |
| [GetWebContents()->GetNativeView() setAutoresizingMask: |
| NSViewWidthSizable|NSViewHeightSizable]; |
| @@ -121,8 +224,14 @@ ConstrainedWebDialogDelegateViewMac::ConstrainedWebDialogDelegateViewMac( |
| base::scoped_nsobject<WebDialogConstrainedWindowSheet> sheet( |
| [[WebDialogConstrainedWindowSheet alloc] initWithCustomWindow:window_ |
| webDialogDelegate:delegate]); |
| - constrained_window_.reset(new ConstrainedWindowMac( |
| - this, web_contents, sheet)); |
| + |
| + if (max_size_.IsEmpty()) { |
| + constrained_window_.reset(ShowWebModalDialogMac( |
| + this, web_contents, sheet)); |
| + } else { |
| + constrained_window_.reset(CreateWebModalDialogMac( |
| + this, web_contents, sheet)); |
| + } |
| impl_->set_window(constrained_window_.get()); |
| } |
| @@ -134,6 +243,23 @@ ConstrainedWebDialogDelegate* ShowConstrainedWebDialog( |
| // Deleted when the dialog closes. |
| ConstrainedWebDialogDelegateViewMac* constrained_delegate = |
| new ConstrainedWebDialogDelegateViewMac( |
| - browser_context, delegate, web_contents); |
| + browser_context, delegate, web_contents, |
| + gfx::Size(), gfx::Size()); |
| + return constrained_delegate; |
| +} |
| + |
| +ConstrainedWebDialogDelegate* ShowConstrainedWebDialogWithAutoResize( |
| + content::BrowserContext* browser_context, |
| + WebDialogDelegate* delegate, |
| + content::WebContents* web_contents, |
| + const gfx::Size& min_size, |
| + const gfx::Size& max_size) { |
| + DCHECK(!min_size.IsEmpty()); |
| + DCHECK(!max_size.IsEmpty()); |
| + // Deleted when the dialog closes. |
| + ConstrainedWebDialogDelegateViewMac* constrained_delegate = |
| + new ConstrainedWebDialogDelegateViewMac( |
| + browser_context, delegate, web_contents, |
| + min_size, max_size); |
| return constrained_delegate; |
| } |