summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.h10
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.mm74
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller_unittest.mm35
-rw-r--r--chrome/browser/cocoa/bookmark_bar_view.mm23
-rw-r--r--chrome/browser/cocoa/bookmark_bar_view_unittest.mm1
-rw-r--r--chrome/browser/cocoa/bookmark_button.h19
-rw-r--r--chrome/browser/cocoa/bookmark_button.mm42
7 files changed, 160 insertions, 44 deletions
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.h b/chrome/browser/cocoa/bookmark_bar_controller.h
index e80cfa1..8ab0e8c 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller.h
+++ b/chrome/browser/cocoa/bookmark_bar_controller.h
@@ -13,6 +13,7 @@
#include "chrome/browser/cocoa/bookmark_bar_bridge.h"
#import "chrome/browser/cocoa/bookmark_bar_state.h"
#import "chrome/browser/cocoa/bookmark_bar_toolbar_view.h"
+#import "chrome/browser/cocoa/bookmark_button.h"
#include "chrome/browser/cocoa/tab_strip_model_observer_bridge.h"
#include "webkit/glue/window_open_disposition.h"
@@ -66,7 +67,9 @@ willAnimateFromState:(bookmarks::VisualState)oldState
// A controller for the bookmark bar in the browser window. Handles showing
// and hiding based on the preference in the given profile.
@interface BookmarkBarController :
- NSViewController<BookmarkBarState, BookmarkBarToolbarViewController> {
+ NSViewController<BookmarkBarState,
+ BookmarkBarToolbarViewController,
+ BookmarkButtonDelegate> {
@private
// The visual state of the bookmark bar. If an animation is running, this is
// set to the "destination" and |lastVisualState_| is set to the "original"
@@ -242,4 +245,9 @@ willAnimateFromState:(bookmarks::VisualState)oldState
- (void)updateTheme:(GTMTheme*)theme;
@end
+// The (internal) |NSPasteboard| type string for bookmark button drags, used for
+// dragging buttons around the bookmark bar. The data for this type is just a
+// pointer to the |BookmarkButton| being dragged.
+extern NSString* kBookmarkButtonDragType;
+
#endif // CHROME_BROWSER_COCOA_BOOKMARK_BAR_CONTROLLER_H_
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.mm b/chrome/browser/cocoa/bookmark_bar_controller.mm
index 79e505a..73a8715 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller.mm
+++ b/chrome/browser/cocoa/bookmark_bar_controller.mm
@@ -98,6 +98,8 @@
// |-bookmarkBar:willAnimateFromState:toState:| in order to inform the
// toolbar of required changes.
+NSString* kBookmarkButtonDragType = @"ChromiumBookmarkButtonDragType";
+
namespace {
// Overlap (in pixels) between the toolbar and the bookmark bar (when showing in
@@ -150,6 +152,11 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
- (int)indexForDragOfButton:(BookmarkButton*)sourceButton
toPoint:(NSPoint)point;
+// Copies the given bookmark node to the given pasteboard, declaring appropriate
+// types (to paste a URL with a title).
+- (void)copyBookmarkNode:(const BookmarkNode*)node
+ toPasteboard:(NSPasteboard*)pboard;
+
- (void)addNode:(const BookmarkNode*)child toMenu:(NSMenu*)menu;
- (void)addFolderNode:(const BookmarkNode*)node toMenu:(NSMenu*)menu;
- (void)tagEmptyMenu:(NSMenu*)menu;
@@ -215,6 +222,13 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
//TODO(dmaclach): Remove -- http://crbug.com/25845
[[self view] removeFromSuperview];
+ // For safety, make sure the buttons can no longer call us.
+ for (BookmarkButton* button in buttons_.get()) {
+ [button setDelegate:nil];
+ [button setTarget:nil];
+ [button setAction:nil];
+ }
+
bridge_.reset(NULL);
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
@@ -863,13 +877,9 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
- (IBAction)copyBookmark:(id)sender {
BookmarkNode* node = [self nodeFromMenuItem:sender];
- const std::string spec = node->GetURL().spec();
- NSString* url = base::SysUTF8ToNSString(spec);
- NSString* title = base::SysWideToNSString(node->GetTitle());
- NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
- [pasteboard declareURLPasteboardWithAdditionalTypes:[NSArray array]
- owner:nil];
- [pasteboard setDataForURL:url title:title];
+ NSPasteboard* pboard = [NSPasteboard generalPasteboard];
+ [self copyBookmarkNode:node
+ toPasteboard:pboard];
}
- (IBAction)deleteBookmark:(id)sender {
@@ -1059,9 +1069,9 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
NSCell* cell = [self cellForBookmarkNode:child];
NSRect frame = [self frameForBookmarkButtonFromCell:cell xOffset:&xOffset];
- NSButton* button = [[[BookmarkButton alloc] initWithFrame:frame]
- autorelease];
- DCHECK(button);
+ scoped_nsobject<BookmarkButton>
+ button([[BookmarkButton alloc] initWithFrame:frame]);
+ DCHECK(button.get());
[buttons_ addObject:button];
// [NSButton setCell:] warns to NOT use setCell: other than in the
@@ -1070,6 +1080,7 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
// object. To honor the assumed semantics, we do nothing with
// NSButton between alloc/init and setCell:.
[button setCell:cell];
+ [button setDelegate:self];
if (child->is_folder()) {
[button setTarget:self];
@@ -1163,6 +1174,7 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
// Peg at right; keep same height as bar.
[button setAutoresizingMask:(NSViewMinXMargin)];
[button setCell:cell];
+ [button setDelegate:self];
[button setTarget:self];
[button setAction:@selector(openFolderMenuFromButton:)];
[buttonView_ addSubview:button];
@@ -1379,6 +1391,31 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
[[self animatableView] stopAnimation];
}
+// (Private)
+- (void)copyBookmarkNode:(const BookmarkNode*)node
+ toPasteboard:(NSPasteboard*)pboard {
+ if (!node) {
+ NOTREACHED();
+ return;
+ }
+
+ if (node->is_folder()) {
+ // TODO(viettrungluu): I'm not sure what we should do, so just declare the
+ // "additional" types we're given for now. Maybe we want to add a list of
+ // URLs? Would we then have to recurse if there were subfolders?
+ // In the meanwhile, we *must* set it to a known state. (If this survives to
+ // a 10.6-only release, it can be replaced with |-clearContents|.)
+ [pboard declareTypes:[NSArray array] owner:nil];
+ } else {
+ const std::string spec = node->GetURL().spec();
+ NSString* url = base::SysUTF8ToNSString(spec);
+ NSString* title = base::SysWideToNSString(node->GetTitle());
+ [pboard declareURLPasteboardWithAdditionalTypes:[NSArray array]
+ owner:nil];
+ [pboard setDataForURL:url title:title];
+ }
+}
+
// Delegate method for |AnimatableView| (a superclass of
// |BookmarkBarToolbarView|).
- (void)animationDidEnd:(NSAnimation*)animation {
@@ -1444,4 +1481,21 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
return 0;
}
+// (BookmarkButtonDelegate protocol)
+- (void)fillPasteboard:(NSPasteboard*)pboard
+ forDragOfButton:(BookmarkButton*)button {
+ if (BookmarkNode* node = [self nodeFromButton:button]) {
+ // Put the bookmark information into the pasteboard, and then write our own
+ // data for |kBookmarkButtonDragType|.
+ [self copyBookmarkNode:node
+ toPasteboard:pboard];
+ [pboard addTypes:[NSArray arrayWithObject:kBookmarkButtonDragType]
+ owner:nil];
+ [pboard setData:[NSData dataWithBytes:&button length:sizeof(button)]
+ forType:kBookmarkButtonDragType];
+ } else {
+ NOTREACHED();
+ }
+}
+
@end
diff --git a/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm b/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
index 91c9fb4..345b96e 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
@@ -10,6 +10,7 @@
#import "chrome/browser/cocoa/bookmark_bar_constants.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
#import "chrome/browser/cocoa/bookmark_bar_view.h"
+#import "chrome/browser/cocoa/bookmark_button.h"
#import "chrome/browser/cocoa/bookmark_menu.h"
#include "chrome/browser/cocoa/browser_test_helper.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
@@ -893,6 +894,40 @@ TEST_F(BookmarkBarControllerTest, TestThemedButton) {
}
}
+// Test that delegates and targets of buttons are cleared on dealloc.
+TEST_F(BookmarkBarControllerTest, TestClearOnDealloc) {
+ // Make some bookmark buttons.
+ BookmarkModel* model = helper_.profile()->GetBookmarkModel();
+ GURL gurls[] = { GURL("http://www.foo.com/"),
+ GURL("http://www.bar.com/"),
+ GURL("http://www.baz.com/") };
+ std::wstring titles[] = { L"foo", L"bar", L"baz" };
+ for (size_t i = 0; i < arraysize(titles); i++)
+ model->SetURLStarred(gurls[i], titles[i], true);
+
+ // Get and retain the buttons so we can examine them after dealloc.
+ scoped_nsobject<NSArray> buttons([[bar_ buttons] retain]);
+ EXPECT_EQ([buttons count], arraysize(titles));
+
+ // Make sure that everything is set.
+ for (BookmarkButton* button in buttons.get()) {
+ ASSERT_TRUE([button isKindOfClass:[BookmarkButton class]]);
+ EXPECT_TRUE([button delegate]);
+ EXPECT_TRUE([button target]);
+ EXPECT_TRUE([button action]);
+ }
+
+ // This will dealloc....
+ bar_.reset();
+
+ // Make sure that everything is cleared.
+ for (BookmarkButton* button in buttons.get()) {
+ EXPECT_FALSE([button delegate]);
+ EXPECT_FALSE([button target]);
+ EXPECT_FALSE([button action]);
+ }
+}
+
// TODO(viettrungluu): figure out how to test animations.
} // namespace
diff --git a/chrome/browser/cocoa/bookmark_bar_view.mm b/chrome/browser/cocoa/bookmark_bar_view.mm
index 2b6d69c..fd7bbe8 100644
--- a/chrome/browser/cocoa/bookmark_bar_view.mm
+++ b/chrome/browser/cocoa/bookmark_bar_view.mm
@@ -99,8 +99,6 @@
// NSDraggingDestination methods
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
- if ([[info draggingPasteboard] containsURLData])
- return NSDragOperationCopy;
if ([[info draggingPasteboard] dataForType:kBookmarkButtonDragType]) {
NSData* data = [[info draggingPasteboard]
dataForType:kBookmarkButtonDragType];
@@ -120,10 +118,13 @@
dropIndicatorPosition_ = x;
[self setNeedsDisplay:YES];
}
- }
- return NSDragOperationMove;
+ return NSDragOperationMove;
+ }
+ // Fall through otherwise.
}
+ if ([[info draggingPasteboard] containsURLData])
+ return NSDragOperationCopy;
return NSDragOperationNone;
}
@@ -191,14 +192,16 @@
- (BOOL)performDragOperation:(id<NSDraggingInfo>)info {
NSPasteboard* pboard = [info draggingPasteboard];
+ if ([pboard dataForType:kBookmarkButtonDragType]) {
+ if ([self performDragOperationForBookmark:info])
+ return YES;
+ // Fall through....
+ }
if ([pboard containsURLData]) {
- return [self performDragOperationForURL:info];
- } else if ([pboard dataForType:kBookmarkButtonDragType]) {
- return [self performDragOperationForBookmark:info];
- } else {
- NOTREACHED() << "Unknown drop type onto bookmark bar.";
- return NO;
+ if ([self performDragOperationForURL:info])
+ return YES;
}
+ return NO;
}
@end // @implementation BookmarkBarView
diff --git a/chrome/browser/cocoa/bookmark_bar_view_unittest.mm b/chrome/browser/cocoa/bookmark_bar_view_unittest.mm
index fabe97d..e99dda1 100644
--- a/chrome/browser/cocoa/bookmark_bar_view_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_bar_view_unittest.mm
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/scoped_nsobject.h"
+#import "chrome/browser/cocoa/bookmark_bar_controller.h"
#import "chrome/browser/cocoa/bookmark_bar_view.h"
#import "chrome/browser/cocoa/bookmark_button.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
diff --git a/chrome/browser/cocoa/bookmark_button.h b/chrome/browser/cocoa/bookmark_button.h
index ea3decc..631a7ba 100644
--- a/chrome/browser/cocoa/bookmark_button.h
+++ b/chrome/browser/cocoa/bookmark_button.h
@@ -4,12 +4,15 @@
#import <Cocoa/Cocoa.h>
+@protocol BookmarkButtonDelegate;
+
// Class for bookmark bar buttons that can be drag sources.
@interface BookmarkButton : NSButton {
@private
BOOL draggable_; // Is this a draggable type of button?
BOOL mayDragStart_; // Set to YES on mouse down, NO on up or drag.
BOOL beingDragged_;
+ id<BookmarkButtonDelegate> delegate_;
// Initial mouse-down to prevent a hair-trigger drag.
NSPoint initialMouseDownLocation_;
@@ -18,7 +21,19 @@
// Enable or disable dragability for special buttons like "Other Bookmarks".
@property BOOL draggable;
-@end
+@property(assign, nonatomic) id<BookmarkButtonDelegate> delegate;
+
+@end // @interface BookmarkButton
+
+// Protocol for a |BookmarkButton|'s delegate, which is responsible for doing
+// things which require information about the bookmark represented by this
+// button.
+@protocol BookmarkButtonDelegate
-extern NSString* kBookmarkButtonDragType;
+// Fill the given pasteboard with appropriate data when the given button is
+// dragged. Since the delegate has no way of providing pasteboard data later,
+// all data must actually be put into the pasteboard and not merely promised.
+- (void)fillPasteboard:(NSPasteboard*)pboard
+ forDragOfButton:(BookmarkButton*)button;
+@end // @protocol BookmarkButtonDelegate
diff --git a/chrome/browser/cocoa/bookmark_button.mm b/chrome/browser/cocoa/bookmark_button.mm
index 38b549f..55c95f6 100644
--- a/chrome/browser/cocoa/bookmark_button.mm
+++ b/chrome/browser/cocoa/bookmark_button.mm
@@ -8,8 +8,6 @@
#import "chrome/browser/cocoa/bookmark_button_cell.h"
#import "third_party/GTM/AppKit/GTMTheme.h"
-NSString* kBookmarkButtonDragType = @"ChromiumBookmarkButtonDragType";
-
namespace {
// Code taken from <http://codereview.chromium.org/180036/diff/3001/3004>.
@@ -32,6 +30,7 @@ const CGFloat kDragImageOpacity = 0.7;
@implementation BookmarkButton
@synthesize draggable = draggable_;
+@synthesize delegate = delegate_;
- (id)initWithFrame:(NSRect)frame {
if ((self = [super initWithFrame:frame])) {
@@ -49,28 +48,28 @@ const CGFloat kDragImageOpacity = 0.7;
// Starting drag. Never start another drag until another mouse down.
mayDragStart_ = NO;
- NSSize dragOffset = NSMakeSize(0.0, 0.0);
- NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
- [pboard declareTypes:[NSArray arrayWithObject:kBookmarkButtonDragType]
- owner:self];
+ if (delegate_) {
+ // Ask our delegate to fill the pasteboard for us.
+ NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
- // This NSData is no longer referenced once the function ends so
- // there is no need to retain/release when placing in here as an
- // opaque pointer.
- [pboard setData:[NSData dataWithBytes:&self length:sizeof(self)]
- forType:kBookmarkButtonDragType];
+ [delegate_ fillPasteboard:pboard forDragOfButton:self];
- // At the moment, moving bookmarks causes their buttons (like me!)
- // to be destroyed and rebuilt. Make sure we don't go away while on
- // the stack.
- [self retain];
+ // At the moment, moving bookmarks causes their buttons (like me!)
+ // to be destroyed and rebuilt. Make sure we don't go away while on
+ // the stack.
+ [self retain];
- CGFloat yAt = [self bounds].size.height;
- [self dragImage:[self dragImage] at:NSMakePoint(0, yAt) offset:dragOffset
- event:event pasteboard:pboard source:self slideBack:YES];
+ CGFloat yAt = [self bounds].size.height;
+ NSSize dragOffset = NSMakeSize(0.0, 0.0);
+ [self dragImage:[self dragImage] at:NSMakePoint(0, yAt) offset:dragOffset
+ event:event pasteboard:pboard source:self slideBack:YES];
- // And we're done.
- [self autorelease];
+ // And we're done.
+ [self autorelease];
+ } else {
+ // Avoid blowing up, but we really shouldn't get here.
+ NOTREACHED();
+ }
}
- (void)draggedImage:(NSImage*)anImage
@@ -81,7 +80,8 @@ const CGFloat kDragImageOpacity = 0.7;
}
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
- return isLocal ? NSDragOperationMove : NSDragOperationNone;
+ return isLocal ? NSDragOperationCopy | NSDragOperationMove
+ : NSDragOperationCopy;
}
- (void)mouseUp:(NSEvent*)theEvent {