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
3 // found in the LICENSE file.
5 #include "base/mac/scoped_nsobject.h"
6 #include "base/strings/string16.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/bookmarks/bookmark_model.h"
9 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
10 #include "chrome/browser/bookmarks/bookmark_test_helpers.h"
11 #include "chrome/browser/profiles/profile.h"
12 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
13 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h"
14 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
15 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h"
16 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h"
17 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
18 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
19 #import "chrome/browser/ui/cocoa/url_drop_target.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/platform_test.h"
23 #import "third_party/mozilla/NSPasteboard+Utils.h"
26 // Some values used for mocks and fakes.
27 const CGFloat kFakeIndicatorPos = 7.0;
28 const NSPoint kPoint = {10, 10};
31 // Fake DraggingInfo, fake BookmarkBarController, fake NSPasteboard...
32 @interface FakeBookmarkDraggingInfo : NSObject {
34 BOOL dragButtonToPong_;
35 BOOL dragButtonToShouldCopy_;
37 BOOL dragBookmarkDataPong_;
38 BOOL dropIndicatorShown_;
39 BOOL draggingEnteredCalled_;
40 // Only mock one type of drag data at a time.
41 NSString* dragDataType_;
42 BookmarkButton* button_; // weak
43 BookmarkModel* bookmarkModel_; // weak
46 @property (nonatomic) BOOL dropIndicatorShown;
47 @property (nonatomic) BOOL draggingEnteredCalled;
48 @property (nonatomic, copy) NSString* dragDataType;
49 @property (nonatomic, assign) BookmarkButton* button;
50 @property (nonatomic, assign) BookmarkModel* bookmarkModel;
53 @implementation FakeBookmarkDraggingInfo
55 @synthesize dropIndicatorShown = dropIndicatorShown_;
56 @synthesize draggingEnteredCalled = draggingEnteredCalled_;
57 @synthesize dragDataType = dragDataType_;
58 @synthesize button = button_;
59 @synthesize bookmarkModel = bookmarkModel_;
62 if ((self = [super init])) {
63 dropIndicatorShown_ = YES;
69 [dragDataType_ release];
74 [dragDataType_ release];
76 dragButtonToPong_ = NO;
78 dragBookmarkDataPong_ = NO;
79 dropIndicatorShown_ = YES;
80 draggingEnteredCalled_ = NO;
81 draggingSource_ = self;
84 - (void)setDraggingSource:(id)draggingSource {
85 draggingSource_ = draggingSource;
88 // NSDragInfo mocking functions.
90 - (id)draggingPasteboard {
94 // So we can look local.
95 - (id)draggingSource {
96 return draggingSource_;
99 - (NSDragOperation)draggingSourceOperationMask {
100 return NSDragOperationCopy | NSDragOperationMove;
103 - (NSPoint)draggingLocation {
107 // NSPasteboard mocking functions.
109 - (BOOL)containsURLData {
110 NSArray* urlTypes = [URLDropTargetHandler handledDragTypes];
112 return [urlTypes containsObject:dragDataType_];
116 - (NSData*)dataForType:(NSString*)type {
117 if (dragDataType_ && [dragDataType_ isEqualToString:type]) {
119 return [NSData dataWithBytes:&button_ length:sizeof(button_)];
121 return [NSData data]; // Return something, anything.
126 // Fake a controller for callback ponging
128 - (BOOL)dragButton:(BookmarkButton*)button to:(NSPoint)point copy:(BOOL)copy {
129 dragButtonToPong_ = YES;
130 dragButtonToShouldCopy_ = copy;
134 - (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point {
139 - (void)getURLs:(NSArray**)outUrls
140 andTitles:(NSArray**)outTitles
141 convertingFilenames:(BOOL)convertFilenames {
144 - (BOOL)dragBookmarkData:(id<NSDraggingInfo>)info {
145 dragBookmarkDataPong_ = YES;
149 - (BOOL)canEditBookmarks {
153 // Confirm the pongs.
155 - (BOOL)dragButtonToPong {
156 return dragButtonToPong_;
159 - (BOOL)dragButtonToShouldCopy {
160 return dragButtonToShouldCopy_;
163 - (BOOL)dragURLsPong {
164 return dragURLsPong_;
167 - (BOOL)dragBookmarkDataPong {
168 return dragBookmarkDataPong_;
171 - (CGFloat)indicatorPosForDragToPoint:(NSPoint)point {
172 return kFakeIndicatorPos;
175 - (BOOL)shouldShowIndicatorShownForPoint:(NSPoint)point {
176 return dropIndicatorShown_;
179 - (BOOL)draggingAllowed:(id<NSDraggingInfo>)info {
183 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
184 draggingEnteredCalled_ = YES;
185 return NSDragOperationNone;
188 - (void)setDropInsertionPos:(CGFloat)where {
191 - (void)clearDropInsertionPos {
198 class BookmarkBarViewTest : public CocoaProfileTest {
200 virtual void SetUp() {
201 CocoaProfileTest::SetUp();
202 view_.reset([[BookmarkBarView alloc] init]);
205 base::scoped_nsobject<BookmarkBarView> view_;
208 TEST_F(BookmarkBarViewTest, CanDragWindow) {
209 EXPECT_FALSE([view_ mouseDownCanMoveWindow]);
212 TEST_F(BookmarkBarViewTest, BookmarkButtonDragAndDrop) {
213 base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
214 [[FakeBookmarkDraggingInfo alloc] init]);
215 [view_ setController:info.get()];
218 BookmarkModel* bookmark_model =
219 BookmarkModelFactory::GetForProfile(profile());
220 const BookmarkNode* node =
221 bookmark_model->AddURL(bookmark_model->bookmark_bar_node(),
223 base::ASCIIToUTF16("Test Bookmark"),
224 GURL("http://www.exmaple.com"));
226 base::scoped_nsobject<BookmarkButtonCell> button_cell(
227 [[BookmarkButtonCell buttonCellForNode:node
230 menuController:nil] retain]);
231 base::scoped_nsobject<BookmarkButton> dragged_button(
232 [[BookmarkButton alloc] init]);
233 [dragged_button setCell:button_cell];
234 [info setDraggingSource:dragged_button.get()];
235 [info setDragDataType:kBookmarkButtonDragType];
236 [info setButton:dragged_button.get()];
237 [info setBookmarkModel:bookmark_model];
238 EXPECT_EQ([view_ draggingEntered:(id)info.get()], NSDragOperationMove);
239 EXPECT_TRUE([view_ performDragOperation:(id)info.get()]);
240 EXPECT_TRUE([info dragButtonToPong]);
241 EXPECT_FALSE([info dragButtonToShouldCopy]);
242 EXPECT_FALSE([info dragURLsPong]);
243 EXPECT_TRUE([info dragBookmarkDataPong]);
246 // When dragging bookmarks across profiles, we should always copy, never move.
247 TEST_F(BookmarkBarViewTest, BookmarkButtonDragAndDropAcrossProfiles) {
248 base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
249 [[FakeBookmarkDraggingInfo alloc] init]);
250 [view_ setController:info.get()];
253 // |other_profile| is owned by the |testing_profile_manager|.
254 TestingProfile* other_profile =
255 testing_profile_manager()->CreateTestingProfile("other");
256 other_profile->CreateBookmarkModel(true);
258 BookmarkModel* bookmark_model =
259 BookmarkModelFactory::GetForProfile(profile());
260 test::WaitForBookmarkModelToLoad(bookmark_model);
262 const BookmarkNode* node =
263 bookmark_model->AddURL(bookmark_model->bookmark_bar_node(),
265 base::ASCIIToUTF16("Test Bookmark"),
266 GURL("http://www.exmaple.com"));
268 base::scoped_nsobject<BookmarkButtonCell> button_cell(
269 [[BookmarkButtonCell buttonCellForNode:node
272 menuController:nil] retain]);
273 base::scoped_nsobject<BookmarkButton> dragged_button(
274 [[BookmarkButton alloc] init]);
275 [dragged_button setCell:button_cell];
276 [info setDraggingSource:dragged_button.get()];
277 [info setDragDataType:kBookmarkButtonDragType];
278 [info setButton:dragged_button.get()];
279 [info setBookmarkModel:BookmarkModelFactory::GetForProfile(other_profile)];
280 EXPECT_EQ([view_ draggingEntered:(id)info.get()], NSDragOperationMove);
281 EXPECT_TRUE([view_ performDragOperation:(id)info.get()]);
282 EXPECT_TRUE([info dragButtonToPong]);
283 EXPECT_TRUE([info dragButtonToShouldCopy]);
284 EXPECT_FALSE([info dragURLsPong]);
285 EXPECT_TRUE([info dragBookmarkDataPong]);
288 TEST_F(BookmarkBarViewTest, URLDragAndDrop) {
289 base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
290 [[FakeBookmarkDraggingInfo alloc] init]);
291 [view_ setController:info.get()];
294 NSArray* dragTypes = [URLDropTargetHandler handledDragTypes];
295 for (NSString* type in dragTypes) {
296 [info setDragDataType:type];
297 EXPECT_EQ([view_ draggingEntered:(id)info.get()], NSDragOperationCopy);
298 EXPECT_TRUE([view_ performDragOperation:(id)info.get()]);
299 EXPECT_FALSE([info dragButtonToPong]);
300 EXPECT_TRUE([info dragURLsPong]);
301 EXPECT_TRUE([info dragBookmarkDataPong]);
306 TEST_F(BookmarkBarViewTest, BookmarkButtonDropIndicator) {
307 base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
308 [[FakeBookmarkDraggingInfo alloc] init]);
309 [view_ setController:info.get()];
312 base::scoped_nsobject<BookmarkButton> dragged_button(
313 [[BookmarkButton alloc] init]);
314 [info setDraggingSource:dragged_button.get()];
315 [info setDragDataType:kBookmarkButtonDragType];
316 EXPECT_FALSE([info draggingEnteredCalled]);
317 EXPECT_EQ([view_ draggingEntered:(id)info.get()], NSDragOperationMove);
318 EXPECT_TRUE([info draggingEnteredCalled]); // Ensure controller pinged.
319 EXPECT_TRUE([view_ dropIndicatorShown]);
320 EXPECT_EQ([view_ dropIndicatorPosition], kFakeIndicatorPos);
322 [info setDropIndicatorShown:NO];
323 EXPECT_EQ([view_ draggingEntered:(id)info.get()], NSDragOperationMove);
324 EXPECT_FALSE([view_ dropIndicatorShown]);