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

Side by Side Diff: chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm

Issue 14130008: Fix race condition if a pulsing bookmark button is deleted while the bookmark bubble controller is … (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: less crash Created 7 years, 8 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 | Annotate | Revision Log
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/bookmarks/bookmark_bubble_controller.h" 5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h"
6 6
7 #include "base/mac/bundle_locations.h" 7 #include "base/mac/bundle_locations.h"
8 #include "base/mac/mac_util.h" 8 #include "base/mac/mac_util.h"
9 #include "base/strings/sys_string_conversions.h" 9 #include "base/strings/sys_string_conversions.h"
10 #include "chrome/browser/bookmarks/bookmark_model.h" 10 #include "chrome/browser/bookmarks/bookmark_model.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 static ChooseAnotherFolder* object = nil; 44 static ChooseAnotherFolder* object = nil;
45 if (!object) { 45 if (!object) {
46 object = [[ChooseAnotherFolder alloc] init]; 46 object = [[ChooseAnotherFolder alloc] init];
47 } 47 }
48 return object; 48 return object;
49 } 49 }
50 50
51 - (id)initWithParentWindow:(NSWindow*)parentWindow 51 - (id)initWithParentWindow:(NSWindow*)parentWindow
52 model:(BookmarkModel*)model 52 model:(BookmarkModel*)model
53 node:(const BookmarkNode*)node 53 node:(const BookmarkNode*)node
54 alreadyBookmarked:(BOOL)alreadyBookmarked { 54 alreadyBookmarked:(BOOL)alreadyBookmarked {
55 DCHECK(model);
56 DCHECK(node);
55 if ((self = [super initWithWindowNibPath:@"BookmarkBubble" 57 if ((self = [super initWithWindowNibPath:@"BookmarkBubble"
56 parentWindow:parentWindow 58 parentWindow:parentWindow
57 anchoredAt:NSZeroPoint])) { 59 anchoredAt:NSZeroPoint])) {
58 model_ = model; 60 model_ = model;
59 node_ = node; 61 node_ = node;
60 alreadyBookmarked_ = alreadyBookmarked; 62 alreadyBookmarked_ = alreadyBookmarked;
61 } 63 }
62 return self; 64 return self;
63 } 65 }
64 66
65 - (void)awakeFromNib { 67 - (void)awakeFromNib {
66 [super awakeFromNib]; 68 [super awakeFromNib];
67 69
68 [[nameTextField_ cell] setUsesSingleLineMode:YES]; 70 [[nameTextField_ cell] setUsesSingleLineMode:YES];
69 } 71 }
70 72
71 // If this is a new bookmark somewhere visible (e.g. on the bookmark 73 // If this is a new bookmark somewhere visible (e.g. on the bookmark
72 // bar), pulse it. Else, call ourself recursively with our parent 74 // bar), pulse it. Else, call ourself recursively with our parent
73 // until we find something visible to pulse. 75 // until we find something visible to pulse.
74 - (void)startPulsingBookmarkButton:(const BookmarkNode*)node { 76 - (void)startPulsingBookmarkButton:(const BookmarkNode*)node {
75 while (node) { 77 while (node) {
76 if ((node->parent() == model_->bookmark_bar_node()) || 78 if ((node->parent() == model_->bookmark_bar_node()) ||
77 (node == model_->other_node())) { 79 (node == model_->other_node())) {
78 pulsingBookmarkNode_ = node; 80 pulsingBookmarkNode_ = node;
81 bookmarkObserver_->StartObservingNode(pulsingBookmarkNode_);
79 NSValue *value = [NSValue valueWithPointer:node]; 82 NSValue *value = [NSValue valueWithPointer:node];
80 NSDictionary *dict = [NSDictionary 83 NSDictionary *dict = [NSDictionary
81 dictionaryWithObjectsAndKeys:value, 84 dictionaryWithObjectsAndKeys:value,
82 bookmark_button::kBookmarkKey, 85 bookmark_button::kBookmarkKey,
83 [NSNumber numberWithBool:YES], 86 [NSNumber numberWithBool:YES],
84 bookmark_button::kBookmarkPulseFlagKey, 87 bookmark_button::kBookmarkPulseFlagKey,
85 nil]; 88 nil];
86 [[NSNotificationCenter defaultCenter] 89 [[NSNotificationCenter defaultCenter]
87 postNotificationName:bookmark_button::kPulseBookmarkButtonNotification 90 postNotificationName:bookmark_button::kPulseBookmarkButtonNotification
88 object:self 91 object:self
89 userInfo:dict]; 92 userInfo:dict];
90 return; 93 return;
91 } 94 }
92 node = node->parent(); 95 node = node->parent();
93 } 96 }
94 } 97 }
95 98
96 - (void)stopPulsingBookmarkButton { 99 - (void)stopPulsingBookmarkButton {
97 if (!pulsingBookmarkNode_) 100 if (!pulsingBookmarkNode_)
98 return; 101 return;
99 NSValue *value = [NSValue valueWithPointer:pulsingBookmarkNode_]; 102 NSValue *value = [NSValue valueWithPointer:pulsingBookmarkNode_];
103 if (bookmarkObserver_)
104 bookmarkObserver_->StopObservingNode(pulsingBookmarkNode_);
100 pulsingBookmarkNode_ = NULL; 105 pulsingBookmarkNode_ = NULL;
101 NSDictionary *dict = [NSDictionary 106 NSDictionary *dict = [NSDictionary
102 dictionaryWithObjectsAndKeys:value, 107 dictionaryWithObjectsAndKeys:value,
103 bookmark_button::kBookmarkKey, 108 bookmark_button::kBookmarkKey,
104 [NSNumber numberWithBool:NO], 109 [NSNumber numberWithBool:NO],
105 bookmark_button::kBookmarkPulseFlagKey, 110 bookmark_button::kBookmarkPulseFlagKey,
106 nil]; 111 nil];
107 [[NSNotificationCenter defaultCenter] 112 [[NSNotificationCenter defaultCenter]
108 postNotificationName:bookmark_button::kPulseBookmarkButtonNotification 113 postNotificationName:bookmark_button::kPulseBookmarkButtonNotification
109 object:self 114 object:self
110 userInfo:dict]; 115 userInfo:dict];
111 } 116 }
112 117
113 // Close the bookmark bubble without changing anything. Unlike a 118 // Close the bookmark bubble without changing anything. Unlike a
114 // typical dialog's OK/Cancel, where Cancel is "do nothing", all 119 // typical dialog's OK/Cancel, where Cancel is "do nothing", all
115 // buttons on the bubble have the capacity to change the bookmark 120 // buttons on the bubble have the capacity to change the bookmark
116 // model. This is an IBOutlet-looking entry point to remove the 121 // model. This is an IBOutlet-looking entry point to remove the
117 // dialog without touching the model. 122 // dialog without touching the model.
118 - (void)dismissWithoutEditing:(id)sender { 123 - (void)dismissWithoutEditing:(id)sender {
119 [self close]; 124 [self close];
120 } 125 }
121 126
122 - (void)windowWillClose:(NSNotification*)notification { 127 - (void)windowWillClose:(NSNotification*)notification {
123 // We caught a close so we don't need to watch for the parent closing. 128 // We caught a close so we don't need to watch for the parent closing.
124 bookmark_observer_.reset(NULL); 129 bookmarkObserver_.reset();
125 [self stopPulsingBookmarkButton]; 130 [self stopPulsingBookmarkButton];
126 [super windowWillClose:notification]; 131 [super windowWillClose:notification];
127 } 132 }
128 133
129 // Override -[BaseBubbleController showWindow:] to tweak bubble location and 134 // Override -[BaseBubbleController showWindow:] to tweak bubble location and
130 // set up UI elements. 135 // set up UI elements.
131 - (void)showWindow:(id)sender { 136 - (void)showWindow:(id)sender {
132 NSWindow* window = [self window]; // Force load the NIB. 137 NSWindow* window = [self window]; // Force load the NIB.
133 NSWindow* parentWindow = self.parentWindow; 138 NSWindow* parentWindow = self.parentWindow;
134 BrowserWindowController* bwc = 139 BrowserWindowController* bwc =
(...skipping 21 matching lines...) Expand all
156 l10n_util::GetNSString(IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED); 161 l10n_util::GetNSString(IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED);
157 [bigTitle_ setStringValue:title]; 162 [bigTitle_ setStringValue:title];
158 } 163 }
159 164
160 [self fillInFolderList]; 165 [self fillInFolderList];
161 166
162 // Ping me when things change out from under us. Unlike a normal 167 // Ping me when things change out from under us. Unlike a normal
163 // dialog, the bookmark bubble's cancel: means "don't add this as a 168 // dialog, the bookmark bubble's cancel: means "don't add this as a
164 // bookmark", not "cancel editing". We must take extra care to not 169 // bookmark", not "cancel editing". We must take extra care to not
165 // touch the bookmark in this selector. 170 // touch the bookmark in this selector.
166 bookmark_observer_.reset(new BookmarkModelObserverForCocoa( 171 bookmarkObserver_.reset(new BookmarkModelObserverForCocoa(
167 node_, model_, 172 model_,
168 self, 173 ^(BOOL nodeWasDeleted) {
169 @selector(dismissWithoutEditing:))); 174 // If a watched node was deleted, the pointer to the pulsing button
175 // is likely stale.
176 if (nodeWasDeleted)
177 pulsingBookmarkNode_ = NULL;
178 [self dismissWithoutEditing:nil];
179 }));
180 bookmarkObserver_->StartObservingNode(node_);
170 181
171 // Pulse something interesting on the bookmark bar. 182 // Pulse something interesting on the bookmark bar.
172 [self startPulsingBookmarkButton:node_]; 183 [self startPulsingBookmarkButton:node_];
173 184
174 [parentWindow addChildWindow:window ordered:NSWindowAbove]; 185 [parentWindow addChildWindow:window ordered:NSWindowAbove];
175 [window makeKeyAndOrderFront:self]; 186 [window makeKeyAndOrderFront:self];
176 [self registerKeyStateEventTap]; 187 [self registerKeyStateEventTap];
177 } 188 }
178 189
179 - (void)close { 190 - (void)close {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 NSInteger idx = [menu indexOfItemWithRepresentedObject:parentValue]; 363 NSInteger idx = [menu indexOfItemWithRepresentedObject:parentValue];
353 DCHECK(idx != -1); 364 DCHECK(idx != -1);
354 [folderPopUpButton_ selectItemAtIndex:idx]; 365 [folderPopUpButton_ selectItemAtIndex:idx];
355 } 366 }
356 367
357 - (NSPopUpButton*)folderPopUpButton { 368 - (NSPopUpButton*)folderPopUpButton {
358 return folderPopUpButton_; 369 return folderPopUpButton_;
359 } 370 }
360 371
361 @end // implementation BookmarkBubbleController(ExposedForUnitTesting) 372 @end // implementation BookmarkBubbleController(ExposedForUnitTesting)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698