Skip to content

Commit 740c410

Browse files
japacibleCommit bot
authored and
Commit bot
committed
[Reland] Enable AutoResize for Constrained Web Dialogs for Mac.
Currently only constrained web dialogs for views (Linux/Windows) are able to autoresize. This change implements the option to pass in minimum and maximum sizes and enabling autoresizing functionality for OSX. This change adds two static functions for options on whether to create a ConstrainedWindowsMac that autoresizes or is of fixed size. The first two patches were reverted because of flaky tests on Mac 10.9. Those patches can be found at: 1. https://codereview.chromium.org/1430023002 2. https://codereview.chromium.org/1446623003 After some investigation, we found that the failures are being caused by an occlusion notifications in cocoa, which is not expected in browser tests. This is currently mac-only. By disabling these notifications in browser tests, we see this patch passing on the swarming bots that were previously failing. See http://crbug/558585. The patch to disable occlusion notifications can be found at: https://codereview.chromium.org/1762883002/ The third patch (same as second patch) broke dialogs like print preview. This was because the change used ui::kWindowSizeDeterminedLater for the dialog window's frame for all constrained web dialogs on mac, not just autoresizable dialogs. That has been amended in this change. That patch can be found here: https://codereview.chromium.org/1699763002/ BUG=217034 Review URL: https://codereview.chromium.org/1781433002 Cr-Commit-Position: refs/heads/master@{#380352}
1 parent 57b0ce2 commit 740c410

28 files changed

+316
-70
lines changed

chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
3939
[[CustomConstrainedWindowSheet alloc]
4040
initWithCustomWindow:[sheet_delegate_ window]]);
41-
constrained_window_.reset(
42-
new ConstrainedWindowMac(this, delegate_->GetWebContents(), sheet));
41+
constrained_window_ =
42+
CreateAndShowWebModalDialogMac(this, delegate_->GetWebContents(), sheet);
4343
[sheet_delegate_ show];
4444
}
4545

chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@
8787
[window setContentView:[view_controller_ view]];
8888
base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
8989
[[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window]);
90-
constrained_window_.reset(
91-
new ConstrainedWindowMac(this, web_contents_, sheet));
90+
constrained_window_ =
91+
CreateAndShowWebModalDialogMac(this, web_contents_, sheet);
9292
}
9393

9494
void CardUnmaskPromptViewBridge::ControllerGone() {

chrome/browser/ui/cocoa/certificate_viewer_mac.mm

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ - (void)displayForWebContents:(content::WebContents*)webContents {
134134
panel_.reset([[SFCertificatePanel alloc] init]);
135135
[panel_ setPolicies:(id) policies.get()];
136136

137-
constrainedWindow_.reset(
138-
new ConstrainedWindowMac(observer_.get(), webContents, self));
137+
constrainedWindow_ =
138+
CreateAndShowWebModalDialogMac(observer_.get(), webContents, self);
139139
}
140140

141141
- (NSWindow*)overlayWindow {
@@ -189,6 +189,10 @@ - (void)updateSheetPosition {
189189
// NOOP
190190
}
191191

192+
- (void)resizeWithNewSize:(NSSize)preferredSize {
193+
// NOOP
194+
}
195+
192196
- (NSWindow*)sheetWindow {
193197
return panel_;
194198
}

chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm

Lines changed: 142 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
1212
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
1313
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_web_dialog_sheet.h"
14+
#include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
15+
#include "content/public/browser/render_view_host.h"
1416
#include "content/public/browser/web_contents.h"
17+
#include "content/public/browser/web_contents_observer.h"
18+
#include "ui/base/cocoa/window_size_constants.h"
1519
#include "ui/gfx/geometry/size.h"
1620
#include "ui/web_dialogs/web_dialog_delegate.h"
1721
#include "ui/web_dialogs/web_dialog_ui.h"
@@ -23,19 +27,61 @@
2327

2428
namespace {
2529

30+
class ConstrainedWebDialogDelegateMac;
31+
32+
// This class is to trigger a resize to the dialog window when
33+
// ResizeDueToAutoResize() is invoked.
34+
class WebDialogWebContentsDelegateMac
35+
: public ui::WebDialogWebContentsDelegate {
36+
public:
37+
WebDialogWebContentsDelegateMac(content::BrowserContext* browser_context,
38+
content::WebContentsObserver* observer,
39+
ConstrainedWebDialogDelegateBase* delegate)
40+
: ui::WebDialogWebContentsDelegate(browser_context,
41+
new ChromeWebContentsHandler()),
42+
observer_(observer),
43+
delegate_(delegate) {
44+
}
45+
~WebDialogWebContentsDelegateMac() override {}
46+
47+
void ResizeDueToAutoResize(content::WebContents* source,
48+
const gfx::Size& preferred_size) override {
49+
if (!observer_->web_contents())
50+
return;
51+
delegate_->ResizeToGivenSize(preferred_size);
52+
}
53+
54+
private:
55+
// These members must outlive the instance.
56+
content::WebContentsObserver* const observer_;
57+
ConstrainedWebDialogDelegateBase* delegate_;
58+
59+
DISALLOW_COPY_AND_ASSIGN(WebDialogWebContentsDelegateMac);
60+
};
61+
2662
class ConstrainedWebDialogDelegateMac
2763
: public ConstrainedWebDialogDelegateBase {
2864
public:
2965
ConstrainedWebDialogDelegateMac(
3066
content::BrowserContext* browser_context,
31-
WebDialogDelegate* delegate)
32-
: ConstrainedWebDialogDelegateBase(browser_context, delegate, NULL) {}
67+
WebDialogDelegate* delegate,
68+
content::WebContentsObserver* observer)
69+
: ConstrainedWebDialogDelegateBase(browser_context, delegate,
70+
new WebDialogWebContentsDelegateMac(browser_context, observer,
71+
this)) {}
3372

3473
// WebDialogWebContentsDelegate interface.
3574
void CloseContents(WebContents* source) override {
3675
window_->CloseWebContentsModalDialog();
3776
}
3877

78+
// ConstrainedWebDialogDelegateBase:
79+
void ResizeToGivenSize(const gfx::Size size) override {
80+
NSSize updated_preferred_size = NSMakeSize(size.width(),
81+
size.height());
82+
[window_->sheet() resizeWithNewSize:updated_preferred_size];
83+
}
84+
3985
void set_window(ConstrainedWindowMac* window) { window_ = window; }
4086
ConstrainedWindowMac* window() const { return window_; }
4187

@@ -50,13 +96,16 @@ void CloseContents(WebContents* source) override {
5096

5197
class ConstrainedWebDialogDelegateViewMac :
5298
public ConstrainedWindowMacDelegate,
53-
public ConstrainedWebDialogDelegate {
99+
public ConstrainedWebDialogDelegate,
100+
public content::WebContentsObserver {
54101

55102
public:
56103
ConstrainedWebDialogDelegateViewMac(
57104
content::BrowserContext* browser_context,
58105
WebDialogDelegate* delegate,
59-
content::WebContents* web_contents);
106+
content::WebContents* web_contents,
107+
const gfx::Size& min_size,
108+
const gfx::Size& max_size);
60109
~ConstrainedWebDialogDelegateViewMac() override {}
61110

62111
// ConstrainedWebDialogDelegate interface
@@ -75,16 +124,37 @@ void ReleaseWebContentsOnDialogClose() override {
75124
gfx::NativeWindow GetNativeDialog() override { return window_; }
76125
WebContents* GetWebContents() override { return impl_->GetWebContents(); }
77126
gfx::Size GetMinimumSize() const override {
78-
NOTIMPLEMENTED();
79-
return gfx::Size();
127+
return min_size_;
80128
}
81129
gfx::Size GetMaximumSize() const override {
82-
NOTIMPLEMENTED();
83-
return gfx::Size();
130+
return max_size_;
84131
}
85132
gfx::Size GetPreferredSize() const override {
86-
NOTIMPLEMENTED();
87-
return gfx::Size();
133+
gfx::Size size;
134+
if (!impl_->closed_via_webui()) {
135+
NSRect frame = [window_ frame];
136+
size = gfx::Size(frame.size.width, frame.size.height);
137+
}
138+
return size;
139+
}
140+
141+
// content::WebContentsObserver:
142+
void RenderViewCreated(content::RenderViewHost* render_view_host) override {
143+
if (IsDialogAutoResizable())
144+
EnableAutoResize();
145+
}
146+
void RenderViewHostChanged(content::RenderViewHost* old_host,
147+
content::RenderViewHost* new_host) override {
148+
if (IsDialogAutoResizable())
149+
EnableAutoResize();
150+
}
151+
void DocumentOnLoadCompletedInMainFrame() override {
152+
if (!IsDialogAutoResizable())
153+
return;
154+
155+
EnableAutoResize();
156+
if (GetWebContents())
157+
constrained_window_->ShowWebContentsModalDialog();
88158
}
89159

90160
// ConstrainedWindowMacDelegate interface
@@ -95,25 +165,56 @@ void OnConstrainedWindowClosed(ConstrainedWindowMac* window) override {
95165
}
96166

97167
private:
168+
void EnableAutoResize() {
169+
if (!GetWebContents())
170+
return;
171+
172+
content::RenderViewHost* render_view_host =
173+
GetWebContents()->GetRenderViewHost();
174+
render_view_host->EnableAutoResize(min_size_, max_size_);
175+
}
176+
177+
// Whether or not the dialog is autoresizable is determined based on whether
178+
// |max_size_| was specified.
179+
bool IsDialogAutoResizable() {
180+
return !max_size_.IsEmpty();
181+
}
182+
98183
scoped_ptr<ConstrainedWebDialogDelegateMac> impl_;
99184
scoped_ptr<ConstrainedWindowMac> constrained_window_;
100185
base::scoped_nsobject<NSWindow> window_;
101186

187+
// Minimum and maximum sizes to determine dialog bounds for auto-resizing.
188+
const gfx::Size min_size_;
189+
const gfx::Size max_size_;
190+
102191
DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateViewMac);
103192
};
104193

105194
ConstrainedWebDialogDelegateViewMac::ConstrainedWebDialogDelegateViewMac(
106195
content::BrowserContext* browser_context,
107196
WebDialogDelegate* delegate,
108-
content::WebContents* web_contents)
109-
: impl_(new ConstrainedWebDialogDelegateMac(browser_context, delegate)) {
197+
content::WebContents* web_contents,
198+
const gfx::Size& min_size,
199+
const gfx::Size& max_size)
200+
: content::WebContentsObserver(web_contents),
201+
impl_(new ConstrainedWebDialogDelegateMac(browser_context, delegate,
202+
this)),
203+
min_size_(min_size),
204+
max_size_(max_size) {
205+
if (IsDialogAutoResizable())
206+
Observe(GetWebContents());
207+
110208
// Create a window to hold web_contents in the constrained sheet:
111209
gfx::Size size;
112210
delegate->GetDialogSize(&size);
113-
NSRect frame = NSMakeRect(0, 0, size.width(), size.height());
211+
// The window size for autoresizing dialogs will be determined at a later
212+
// time.
213+
NSRect frame = IsDialogAutoResizable() ? ui::kWindowSizeDeterminedLater :
214+
NSMakeRect(0, 0, size.width(), size.height());
114215

115-
window_.reset(
116-
[[ConstrainedWindowCustomWindow alloc] initWithContentRect:frame]);
216+
window_.reset([[ConstrainedWindowCustomWindow alloc]
217+
initWithContentRect:frame]);
117218
[GetWebContents()->GetNativeView() setFrame:frame];
118219
[GetWebContents()->GetNativeView() setAutoresizingMask:
119220
NSViewWidthSizable|NSViewHeightSizable];
@@ -122,8 +223,14 @@ void OnConstrainedWindowClosed(ConstrainedWindowMac* window) override {
122223
base::scoped_nsobject<WebDialogConstrainedWindowSheet> sheet(
123224
[[WebDialogConstrainedWindowSheet alloc] initWithCustomWindow:window_
124225
webDialogDelegate:delegate]);
125-
constrained_window_.reset(new ConstrainedWindowMac(
126-
this, web_contents, sheet));
226+
227+
if (IsDialogAutoResizable()) {
228+
constrained_window_ = CreateWebModalDialogMac(
229+
this, web_contents, sheet);
230+
} else {
231+
constrained_window_ = CreateAndShowWebModalDialogMac(
232+
this, web_contents, sheet);
233+
}
127234

128235
impl_->set_window(constrained_window_.get());
129236
}
@@ -135,6 +242,23 @@ void OnConstrainedWindowClosed(ConstrainedWindowMac* window) override {
135242
// Deleted when the dialog closes.
136243
ConstrainedWebDialogDelegateViewMac* constrained_delegate =
137244
new ConstrainedWebDialogDelegateViewMac(
138-
browser_context, delegate, web_contents);
245+
browser_context, delegate, web_contents,
246+
gfx::Size(), gfx::Size());
247+
return constrained_delegate;
248+
}
249+
250+
ConstrainedWebDialogDelegate* ShowConstrainedWebDialogWithAutoResize(
251+
content::BrowserContext* browser_context,
252+
WebDialogDelegate* delegate,
253+
content::WebContents* web_contents,
254+
const gfx::Size& min_size,
255+
const gfx::Size& max_size) {
256+
DCHECK(!min_size.IsEmpty());
257+
DCHECK(!max_size.IsEmpty());
258+
// Deleted when the dialog closes.
259+
ConstrainedWebDialogDelegateViewMac* constrained_delegate =
260+
new ConstrainedWebDialogDelegateViewMac(
261+
browser_context, delegate, web_contents,
262+
min_size, max_size);
139263
return constrained_delegate;
140264
}

chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ - (void)updateSheetPosition {
7373
[customWindow_ setFrameOrigin:origin];
7474
}
7575

76+
- (void)resizeWithNewSize:(NSSize)size {
77+
// NOOP
78+
}
79+
7680
- (NSWindow*)sheetWindow {
7781
return customWindow_;
7882
}

chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
#import <Cocoa/Cocoa.h>
99

10+
#include "base/mac/scoped_nsobject.h"
11+
#include "components/web_modal/web_contents_modal_dialog_manager.h"
12+
1013
namespace content {
1114
class WebContents;
1215
}
@@ -21,6 +24,18 @@ class ConstrainedWindowMacDelegate {
2124
virtual void OnConstrainedWindowClosed(ConstrainedWindowMac* window) = 0;
2225
};
2326

27+
// Creates a ConstrainedWindowMac, shows the dialog, and returns it.
28+
scoped_ptr<ConstrainedWindowMac> CreateAndShowWebModalDialogMac(
29+
ConstrainedWindowMacDelegate* delegate,
30+
content::WebContents* web_contents,
31+
id<ConstrainedWindowSheet> sheet);
32+
33+
// Creates a ConstrainedWindowMac and returns it.
34+
scoped_ptr<ConstrainedWindowMac> CreateWebModalDialogMac(
35+
ConstrainedWindowMacDelegate* delegate,
36+
content::WebContents* web_contents,
37+
id<ConstrainedWindowSheet> sheet);
38+
2439
// Constrained window implementation for Mac.
2540
// Normally an instance of this class is owned by the delegate. The delegate
2641
// should delete the instance when the window is closed.
@@ -31,20 +46,34 @@ class ConstrainedWindowMac {
3146
id<ConstrainedWindowSheet> sheet);
3247
~ConstrainedWindowMac();
3348

49+
// Shows the constrained window.
50+
void ShowWebContentsModalDialog();
51+
3452
// Closes the constrained window.
3553
void CloseWebContentsModalDialog();
3654

3755
SingleWebContentsDialogManagerCocoa* manager() const { return manager_; }
3856
void set_manager(SingleWebContentsDialogManagerCocoa* manager) {
3957
manager_ = manager;
4058
}
59+
id<ConstrainedWindowSheet> sheet() const { return sheet_.get(); }
4160

4261
// Called by |manager_| when the dialog is closing.
4362
void OnDialogClosing();
4463

64+
// Whether or not the dialog was shown. If the dialog is auto-resizable, it
65+
// is hidden until its WebContents initially loads.
66+
bool DialogWasShown();
67+
68+
// Gets the dialog manager for |web_contents_|.
69+
web_modal::WebContentsModalDialogManager* GetDialogManager();
70+
4571
private:
4672
ConstrainedWindowMacDelegate* delegate_; // weak, owns us.
4773
SingleWebContentsDialogManagerCocoa* manager_; // weak, owned by WCMDM.
74+
content::WebContents* web_contents_; // weak, owned by dialog initiator.
75+
base::scoped_nsprotocol<id<ConstrainedWindowSheet>> sheet_;
76+
scoped_ptr<SingleWebContentsDialogManagerCocoa> native_manager_;
4877
};
4978

5079
#endif // CHROME_BROWSER_UI_COCOA_CONSTRAINED_WINDOW_CONSTRAINED_WINDOW_MAC_

0 commit comments

Comments
 (0)