Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm

Issue 653843002: Mac: Attach Extension NSViews to the view hierarchy before creating renderers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove DCHECK Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h" 5 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/chrome_notification_types.h"
(...skipping 28 matching lines...) Expand all
39 39
40 // Given a value and a rage, clamp the value into the range. 40 // Given a value and a rage, clamp the value into the range.
41 CGFloat Clamp(CGFloat value, CGFloat min, CGFloat max) { 41 CGFloat Clamp(CGFloat value, CGFloat min, CGFloat max) {
42 return std::max(min, std::min(max, value)); 42 return std::max(min, std::min(max, value));
43 } 43 }
44 44
45 } // namespace 45 } // namespace
46 46
47 @interface ExtensionPopupController (Private) 47 @interface ExtensionPopupController (Private)
48 // Callers should be using the public static method for initialization. 48 // Callers should be using the public static method for initialization.
49 // NOTE: This takes ownership of |host|. 49 - (id)initWithParentWindow:(NSWindow*)parentWindow
50 - (id)initWithHost:(extensions::ExtensionViewHost*)host 50 anchoredAt:(NSPoint)anchoredAt
51 parentWindow:(NSWindow*)parentWindow 51 arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation
52 anchoredAt:(NSPoint)anchoredAt 52 devMode:(BOOL)devMode;
53 arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation 53
54 devMode:(BOOL)devMode; 54 // Set the ExtensionViewHost, taking ownership.
55 - (void)setExtensionViewHost:(scoped_ptr<extensions::ExtensionViewHost>)host;
55 56
56 // Called when the extension's hosted NSView has been resized. 57 // Called when the extension's hosted NSView has been resized.
57 - (void)extensionViewFrameChanged; 58 - (void)extensionViewFrameChanged;
58 59
59 // Called when the extension's size changes. 60 // Called when the extension's size changes.
60 - (void)onSizeChanged:(NSSize)newSize; 61 - (void)onSizeChanged:(NSSize)newSize;
61 62
62 // Called when the extension view is shown. 63 // Called when the extension view is shown.
63 - (void)onViewDidShow; 64 - (void)onViewDidShow;
64 65
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 // know what it is for notifications, but our ExtensionViewHost may not be 144 // know what it is for notifications, but our ExtensionViewHost may not be
144 // valid. 145 // valid.
145 WebContents* web_contents_; 146 WebContents* web_contents_;
146 base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_; 147 base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_;
147 }; 148 };
148 149
149 @implementation ExtensionPopupController 150 @implementation ExtensionPopupController
150 151
151 @synthesize extensionId = extensionId_; 152 @synthesize extensionId = extensionId_;
152 153
153 - (id)initWithHost:(extensions::ExtensionViewHost*)host 154 - (id)initWithParentWindow:(NSWindow*)parentWindow
154 parentWindow:(NSWindow*)parentWindow 155 anchoredAt:(NSPoint)anchoredAt
155 anchoredAt:(NSPoint)anchoredAt 156 arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation
156 arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation 157 devMode:(BOOL)devMode {
157 devMode:(BOOL)devMode {
158 base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc] 158 base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
159 initWithContentRect:ui::kWindowSizeDeterminedLater 159 initWithContentRect:ui::kWindowSizeDeterminedLater
160 styleMask:NSBorderlessWindowMask 160 styleMask:NSBorderlessWindowMask
161 backing:NSBackingStoreBuffered 161 backing:NSBackingStoreBuffered
162 defer:YES]); 162 defer:YES]);
163 if (!window.get()) 163 if (!window.get())
164 return nil; 164 return nil;
165 165
166 anchoredAt = [parentWindow convertBaseToScreen:anchoredAt]; 166 anchoredAt = [parentWindow convertBaseToScreen:anchoredAt];
167 if ((self = [super initWithWindow:window 167 if ((self = [super initWithWindow:window
168 parentWindow:parentWindow 168 parentWindow:parentWindow
169 anchoredAt:anchoredAt])) { 169 anchoredAt:anchoredAt])) {
170 host_.reset(host);
171 extensionId_ = host_->extension_id();
172 beingInspected_ = devMode; 170 beingInspected_ = devMode;
173 ignoreWindowDidResignKey_ = NO; 171 ignoreWindowDidResignKey_ = NO;
174 172 [[self bubble] setArrowLocation:arrowLocation];
175 InfoBubbleView* view = self.bubble;
176 [view setArrowLocation:arrowLocation];
177
178 extensionView_ = host->view()->GetNativeView();
179 container_.reset(new ExtensionPopupContainer(self));
180 static_cast<ExtensionViewMac*>(host->view())
181 ->set_container(container_.get());
182
183 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
184 [center addObserver:self
185 selector:@selector(extensionViewFrameChanged)
186 name:NSViewFrameDidChangeNotification
187 object:extensionView_];
188
189 [view addSubview:extensionView_];
190
191 notificationBridge_.reset(new DevtoolsNotificationBridge(self));
192 registrar_.reset(new content::NotificationRegistrar);
193 if (beingInspected_) {
194 // Listen for the extension to finish loading so the dev tools can be
195 // opened.
196 registrar_->Add(notificationBridge_.get(),
197 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
198 content::Source<BrowserContext>(host->browser_context()));
199 }
200 } 173 }
201 return self; 174 return self;
202 } 175 }
203 176
204 - (void)dealloc { 177 - (void)dealloc {
205 [[NSNotificationCenter defaultCenter] removeObserver:self]; 178 [[NSNotificationCenter defaultCenter] removeObserver:self];
206 [super dealloc]; 179 [super dealloc];
207 } 180 }
208 181
209 - (void)showDevTools { 182 - (void)showDevTools {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 devMode:(BOOL)devMode { 251 devMode:(BOOL)devMode {
279 DCHECK([NSThread isMainThread]); 252 DCHECK([NSThread isMainThread]);
280 DCHECK(browser); 253 DCHECK(browser);
281 if (!browser) 254 if (!browser)
282 return nil; 255 return nil;
283 256
284 // If we click the browser/page action again, we should close the popup. 257 // If we click the browser/page action again, we should close the popup.
285 // Make Mac behavior the same with Windows and others. 258 // Make Mac behavior the same with Windows and others.
286 if (gPopup) { 259 if (gPopup) {
287 std::string extension_id = url.host(); 260 std::string extension_id = url.host();
288 extensions::ExtensionViewHost* host = [gPopup extensionViewHost]; 261 std::string old_extension_id = [gPopup extensionViewHost]->extension_id();
289 if (extension_id == host->extension_id()) { 262 [gPopup close]; // Starts the animation to fade out the popup.
290 [gPopup close]; 263 if (extension_id == old_extension_id)
291 return nil; 264 return nil;
292 }
293 } 265 }
294 266
295 extensions::ExtensionViewHost* host = 267 // Create the popup first. This establishes an initially hidden NSWindow so
296 extensions::ExtensionViewHostFactory::CreatePopupHost(url, browser); 268 // that the renderer is able to gather correct screen metrics for the initial
269 // paint.
270 gPopup = [[ExtensionPopupController alloc]
271 initWithParentWindow:browser->window()->GetNativeWindow()
272 anchoredAt:anchoredAt
273 arrowLocation:arrowLocation
274 devMode:devMode];
275
276 scoped_ptr<extensions::ExtensionViewHost> host(
277 extensions::ExtensionViewHostFactory::CreatePopupHost(url, browser));
297 DCHECK(host); 278 DCHECK(host);
298 if (!host) 279 [gPopup setExtensionViewHost:host.Pass()];
299 return nil;
300
301 [gPopup close];
302
303 // Takes ownership of |host|. Also will autorelease itself when the popup is
304 // closed, so no need to do that here.
305 gPopup = [[ExtensionPopupController alloc]
306 initWithHost:host
307 parentWindow:browser->window()->GetNativeWindow()
308 anchoredAt:anchoredAt
309 arrowLocation:arrowLocation
310 devMode:devMode];
311 return gPopup; 280 return gPopup;
312 } 281 }
313 282
314 + (ExtensionPopupController*)popup { 283 + (ExtensionPopupController*)popup {
315 return gPopup; 284 return gPopup;
316 } 285 }
317 286
287 - (void)setExtensionViewHost:(scoped_ptr<extensions::ExtensionViewHost>)host {
288 DCHECK(!host_);
289 DCHECK(host);
290 host_.swap(host);
291
292 extensionId_ = host_->extension_id();
293 container_.reset(new ExtensionPopupContainer(self));
294 ExtensionViewMac* hostView = static_cast<ExtensionViewMac*>(host_->view());
295 hostView->set_container(container_.get());
296 hostView->CreateWidgetHostViewIn([self bubble]);
297
298 extensionView_ = hostView->GetNativeView();
299
300 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
301 [center addObserver:self
302 selector:@selector(extensionViewFrameChanged)
303 name:NSViewFrameDidChangeNotification
304 object:extensionView_];
305
306 notificationBridge_.reset(new DevtoolsNotificationBridge(self));
307 registrar_.reset(new content::NotificationRegistrar);
308 if (beingInspected_) {
309 // Listen for the extension to finish loading so the dev tools can be
310 // opened.
311 registrar_->Add(notificationBridge_.get(),
312 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
313 content::Source<BrowserContext>(host_->browser_context()));
314 }
315 }
316
318 - (void)extensionViewFrameChanged { 317 - (void)extensionViewFrameChanged {
319 // If there are no changes in the width or height of the frame, then ignore. 318 // If there are no changes in the width or height of the frame, then ignore.
320 if (NSEqualSizes([extensionView_ frame].size, extensionFrame_.size)) 319 if (NSEqualSizes([extensionView_ frame].size, extensionFrame_.size))
321 return; 320 return;
322 321
323 extensionFrame_ = [extensionView_ frame]; 322 extensionFrame_ = [extensionView_ frame];
324 // Constrain the size of the view. 323 // Constrain the size of the view.
325 [extensionView_ setFrameSize:NSMakeSize( 324 [extensionView_ setFrameSize:NSMakeSize(
326 Clamp(NSWidth(extensionFrame_), 325 Clamp(NSWidth(extensionFrame_),
327 ExtensionViewMac::kMinWidth, 326 ExtensionViewMac::kMinWidth,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 // the notification is fired (and consequently the view contents have loaded). 374 // the notification is fired (and consequently the view contents have loaded).
376 if (![window isVisible]) { 375 if (![window isVisible]) {
377 [self showWindow:self]; 376 [self showWindow:self];
378 } 377 }
379 } 378 }
380 379
381 - (void)onSizeChanged:(NSSize)newSize { 380 - (void)onSizeChanged:(NSSize)newSize {
382 // When we update the size, the window will become visible. Stay hidden until 381 // When we update the size, the window will become visible. Stay hidden until
383 // the host is loaded. 382 // the host is loaded.
384 pendingSize_ = newSize; 383 pendingSize_ = newSize;
385 if (!host_->did_stop_loading()) 384 if (!host_ || !host_->did_stop_loading())
386 return; 385 return;
387 386
388 // No need to use CA here, our caller calls us repeatedly to animate the 387 // No need to use CA here, our caller calls us repeatedly to animate the
389 // resizing. 388 // resizing.
390 NSRect frame = [extensionView_ frame]; 389 NSRect frame = [extensionView_ frame];
391 frame.size = newSize; 390 frame.size = newSize;
392 391
393 // |new_size| is in pixels. Convert to view units. 392 // |new_size| is in pixels. Convert to view units.
394 frame.size = [extensionView_ convertSize:frame.size fromView:nil]; 393 frame.size = [extensionView_ convertSize:frame.size fromView:nil];
395 394
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 return minSize; 432 return minSize;
434 } 433 }
435 434
436 // Private (TestingAPI) 435 // Private (TestingAPI)
437 + (NSSize)maxPopupSize { 436 + (NSSize)maxPopupSize {
438 NSSize maxSize = {ExtensionViewMac::kMaxWidth, ExtensionViewMac::kMaxHeight}; 437 NSSize maxSize = {ExtensionViewMac::kMaxWidth, ExtensionViewMac::kMaxHeight};
439 return maxSize; 438 return maxSize;
440 } 439 }
441 440
442 @end 441 @end
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_view_host.cc ('k') | chrome/browser/ui/cocoa/extensions/extension_view_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698