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

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_mac.mm

Issue 3534010: Mac: Fix crash when destroying RWHVMacs that use accelerated drawing. (Closed)
Patch Set: '' Created 10 years, 2 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
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 #include <QuartzCore/QuartzCore.h> 5 #include <QuartzCore/QuartzCore.h>
6 6
7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
8 8
9 #include "chrome/browser/chrome_thread.h" 9 #include "chrome/browser/chrome_thread.h"
10 #include "app/surface/io_surface_support_mac.h" 10 #include "app/surface/io_surface_support_mac.h"
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 163
164 // -globalFrameDidChange: can be called recursively, this counts how often it 164 // -globalFrameDidChange: can be called recursively, this counts how often it
165 // holds the CGL lock. 165 // holds the CGL lock.
166 int globalFrameDidChangeCGLLockCount_; 166 int globalFrameDidChangeCGLLockCount_;
167 } 167 }
168 168
169 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r 169 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r
170 pluginHandle:(gfx::PluginWindowHandle)pluginHandle; 170 pluginHandle:(gfx::PluginWindowHandle)pluginHandle;
171 - (void)drawView; 171 - (void)drawView;
172 172
173 // NSViews autorelease subviews when they die. The RWHVMac gets destroyed when
174 // RHWVCocoa gets dealloc'd, which means the AcceleratedPluginView child views
175 // can be around a little longer than the RWHVMac. This is called when the
176 // RWHVMac is about to be deleted (but it's still valid while this method runs).
177 - (void)onRenderWidgetHostViewGone;
178
173 // This _must_ be atomic, since it's accessed from several threads. 179 // This _must_ be atomic, since it's accessed from several threads.
174 @property BOOL surfaceWasSwapped; 180 @property BOOL surfaceWasSwapped;
175 181
176 // This _must_ be atomic, since it's accessed from several threads. 182 // This _must_ be atomic, since it's accessed from several threads.
177 @property NSSize cachedSize; 183 @property NSSize cachedSize;
178 @end 184 @end
179 185
180 @implementation AcceleratedPluginView 186 @implementation AcceleratedPluginView
181 @synthesize surfaceWasSwapped = surfaceWasSwapped_; 187 @synthesize surfaceWasSwapped = surfaceWasSwapped_;
182 @synthesize cachedSize = cachedSize_; 188 @synthesize cachedSize = cachedSize_;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 [glContext_ setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; 246 [glContext_ setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
241 247
242 // Set up a display link to do OpenGL rendering on a background thread. 248 // Set up a display link to do OpenGL rendering on a background thread.
243 CVDisplayLinkCreateWithActiveCGDisplays(&displayLink_); 249 CVDisplayLinkCreateWithActiveCGDisplays(&displayLink_);
244 } 250 }
245 return self; 251 return self;
246 } 252 }
247 253
248 - (void)dealloc { 254 - (void)dealloc {
249 CVDisplayLinkRelease(displayLink_); 255 CVDisplayLinkRelease(displayLink_);
256 if (renderWidgetHostView_)
257 renderWidgetHostView_->DeallocFakePluginWindowHandle(pluginHandle_);
250 [[NSNotificationCenter defaultCenter] removeObserver:self]; 258 [[NSNotificationCenter defaultCenter] removeObserver:self];
251 [super dealloc]; 259 [super dealloc];
252 } 260 }
253 261
254 - (void)drawView { 262 - (void)drawView {
255 // Called on a background thread. Synchronized via the CGL context lock. 263 // Called on a background thread. Synchronized via the CGL context lock.
256 CGLLockContext(cglContext_); 264 CGLLockContext(cglContext_);
257 265
258 // TODO(thakis): Pixel or view coordinates for size? 266 // TODO(thakis): Pixel or view coordinates for size?
259 renderWidgetHostView_->DrawAcceleratedSurfaceInstance( 267 renderWidgetHostView_->DrawAcceleratedSurfaceInstance(
260 cglContext_, pluginHandle_, [self cachedSize]); 268 cglContext_, pluginHandle_, [self cachedSize]);
261 269
262 CGLFlushDrawable(cglContext_); 270 CGLFlushDrawable(cglContext_);
263 CGLUnlockContext(cglContext_); 271 CGLUnlockContext(cglContext_);
264 } 272 }
265 273
274 - (void)onRenderWidgetHostViewGone {
275 CGLLockContext(cglContext_);
276 // Deallocate the plugin handle while we still can.
277 renderWidgetHostView_->DeallocFakePluginWindowHandle(pluginHandle_);
278 renderWidgetHostView_ = NULL;
279 CGLUnlockContext(cglContext_);
280 }
281
266 - (void)drawRect:(NSRect)rect { 282 - (void)drawRect:(NSRect)rect {
267 if (!CommandLine::ForCurrentProcess()->HasSwitch( 283 if (!CommandLine::ForCurrentProcess()->HasSwitch(
268 switches::kDisableHolePunching)) { 284 switches::kDisableHolePunching)) {
269 const NSRect* dirtyRects; 285 const NSRect* dirtyRects;
270 int dirtyRectCount; 286 int dirtyRectCount;
271 [self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount]; 287 [self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount];
272 288
273 // Punch a hole so that the OpenGL view shows through. 289 // Punch a hole so that the OpenGL view shows through.
274 [[NSColor clearColor] set]; 290 [[NSColor clearColor] set];
275 NSRectFillList(dirtyRects, dirtyRectCount); 291 NSRectFillList(dirtyRects, dirtyRectCount);
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 // message and can kill itself. Alas, on the Mac, views cannot capture events 707 // message and can kill itself. Alas, on the Mac, views cannot capture events
692 // outside of themselves. On Windows, if Destroy is being called on a view, 708 // outside of themselves. On Windows, if Destroy is being called on a view,
693 // then the event causing the destroy had also cancelled any popups by the 709 // then the event causing the destroy had also cancelled any popups by the
694 // time Destroy() was called. On the Mac we have to destroy all the popups 710 // time Destroy() was called. On the Mac we have to destroy all the popups
695 // ourselves. 711 // ourselves.
696 712
697 if (!is_popup_menu_) { 713 if (!is_popup_menu_) {
698 // Depth-first destroy all popups. Use ShutdownHost() to enforce 714 // Depth-first destroy all popups. Use ShutdownHost() to enforce
699 // deepest-first ordering. 715 // deepest-first ordering.
700 for (NSView* subview in [cocoa_view_ subviews]) { 716 for (NSView* subview in [cocoa_view_ subviews]) {
701 if (![subview isKindOfClass:[RenderWidgetHostViewCocoa class]]) 717 if ([subview isKindOfClass:[RenderWidgetHostViewCocoa class]]) {
702 continue; // Skip accelerated views. 718 [static_cast<RenderWidgetHostViewCocoa*>(subview)
703 719 renderWidgetHostViewMac]->ShutdownHost();
704 [static_cast<RenderWidgetHostViewCocoa*>(subview) 720 } else if ([subview isKindOfClass:[AcceleratedPluginView class]]) {
705 renderWidgetHostViewMac]->ShutdownHost(); 721 [static_cast<AcceleratedPluginView*>(subview)
722 onRenderWidgetHostViewGone];
723 }
706 } 724 }
707 725
708 // We've been told to destroy. 726 // We've been told to destroy.
709 [cocoa_view_ retain]; 727 [cocoa_view_ retain];
710 [cocoa_view_ removeFromSuperview]; 728 [cocoa_view_ removeFromSuperview];
711 [cocoa_view_ autorelease]; 729 [cocoa_view_ autorelease];
712 } else { 730 } else {
713 // From the renderer's perspective, the pop-up menu is represented by a 731 // From the renderer's perspective, the pop-up menu is represented by a
714 // RenderWidget. The actual Mac implementation uses a native pop-up menu 732 // RenderWidget. The actual Mac implementation uses a native pop-up menu
715 // and doesn't actually make use of the RenderWidgetHostViewCocoa that 733 // and doesn't actually make use of the RenderWidgetHostViewCocoa that
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 void RenderWidgetHostViewMac::DestroyFakePluginWindowHandle( 891 void RenderWidgetHostViewMac::DestroyFakePluginWindowHandle(
874 gfx::PluginWindowHandle window) { 892 gfx::PluginWindowHandle window) {
875 CHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 893 CHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
876 PluginViewMap::iterator it = plugin_views_.find(window); 894 PluginViewMap::iterator it = plugin_views_.find(window);
877 DCHECK(plugin_views_.end() != it); 895 DCHECK(plugin_views_.end() != it);
878 if (plugin_views_.end() == it) { 896 if (plugin_views_.end() == it) {
879 return; 897 return;
880 } 898 }
881 [it->second removeFromSuperview]; 899 [it->second removeFromSuperview];
882 plugin_views_.erase(it); 900 plugin_views_.erase(it);
901
902 // The view's dealloc will call DeallocFakePluginWindowHandle(), which will
903 // remove the handle from |plugin_container_manager_|. This code path is
904 // taken if a plugin is removed, but the RWHVMac itself stays alive.
905 }
906
907 // This is called by AcceleratedPluginView's -dealloc.
908 void RenderWidgetHostViewMac::DeallocFakePluginWindowHandle(
909 gfx::PluginWindowHandle window) {
883 plugin_container_manager_.DestroyFakePluginWindowHandle(window); 910 plugin_container_manager_.DestroyFakePluginWindowHandle(window);
884 } 911 }
885 912
886 void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface( 913 void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface(
887 gfx::PluginWindowHandle window, 914 gfx::PluginWindowHandle window,
888 int32 width, 915 int32 width,
889 int32 height, 916 int32 height,
890 uint64 io_surface_identifier) { 917 uint64 io_surface_identifier) {
891 CHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 918 CHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
892 plugin_container_manager_.SetSizeAndIOSurface(window, 919 plugin_container_manager_.SetSizeAndIOSurface(window,
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults]; 1027 NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults];
1001 [user_defaults addSuiteNamed:@"com.apple.universalaccess"]; 1028 [user_defaults addSuiteNamed:@"com.apple.universalaccess"];
1002 return 1 == [user_defaults integerForKey:@"voiceOverOnOffKey"]; 1029 return 1 == [user_defaults integerForKey:@"voiceOverOnOffKey"];
1003 } 1030 }
1004 1031
1005 namespace { 1032 namespace {
1006 1033
1007 // Adjusts an NSRect in Cocoa screen coordinates to have an origin in the upper 1034 // Adjusts an NSRect in Cocoa screen coordinates to have an origin in the upper
1008 // left of the primary screen (Carbon coordinates), and stuffs it into a 1035 // left of the primary screen (Carbon coordinates), and stuffs it into a
1009 // gfx::Rect. 1036 // gfx::Rect.
1010 gfx::Rect FlipNSRectToRectScreen(const NSRect rect) { 1037 gfx::Rect FlipNSRectToRectScreen(const NSRect& rect) {
1011 gfx::Rect new_rect(NSRectToCGRect(rect)); 1038 gfx::Rect new_rect(NSRectToCGRect(rect));
1012 if ([[NSScreen screens] count] > 0) { 1039 if ([[NSScreen screens] count] > 0) {
1013 new_rect.set_y([[[NSScreen screens] objectAtIndex:0] frame].size.height - 1040 new_rect.set_y([[[NSScreen screens] objectAtIndex:0] frame].size.height -
1014 new_rect.y() - new_rect.height()); 1041 new_rect.y() - new_rect.height());
1015 } 1042 }
1016 return new_rect; 1043 return new_rect;
1017 } 1044 }
1018 1045
1019 // Returns the window that visually contains the given view. This is different 1046 // Returns the window that visually contains the given view. This is different
1020 // from [view window] in the case of tab dragging, where the view's owning 1047 // from [view window] in the case of tab dragging, where the view's owning
(...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after
2449 if (!string) return NO; 2476 if (!string) return NO;
2450 2477
2451 // If the user is currently using an IME, confirm the IME input, 2478 // If the user is currently using an IME, confirm the IME input,
2452 // and then insert the text from the service, the same as TextEdit and Safari. 2479 // and then insert the text from the service, the same as TextEdit and Safari.
2453 [self confirmComposition]; 2480 [self confirmComposition];
2454 [self insertText:string]; 2481 [self insertText:string];
2455 return YES; 2482 return YES;
2456 } 2483 }
2457 2484
2458 @end 2485 @end
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698