1 // Copyright 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 "chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/prefs/pref_service.h"
9 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/bookmarks/browser/bookmark_model.h"
14 #include "components/bookmarks/browser/bookmark_node_data.h"
15 #include "components/user_prefs/user_prefs.h"
16 #include "ui/base/dragdrop/drag_drop_types.h"
17 #include "ui/base/dragdrop/os_exchange_data.h"
18 #include "ui/events/event.h"
19 #include "ui/views/drag_utils.h"
20 #include "ui/views/widget/widget.h"
24 void DragBookmarks(Profile
* profile
,
25 const std::vector
<const BookmarkNode
*>& nodes
,
27 ui::DragDropTypes::DragEventSource source
) {
28 DCHECK(!nodes
.empty());
30 // Set up our OLE machinery
31 ui::OSExchangeData data
;
32 BookmarkNodeData
drag_data(nodes
);
33 drag_data
.Write(profile
->GetPath(), &data
);
35 // Allow nested message loop so we get DnD events as we drag this around.
36 bool was_nested
= base::MessageLoop::current()->IsNested();
37 base::MessageLoop::current()->SetNestableTasksAllowed(true);
39 int operation
= ui::DragDropTypes::DRAG_COPY
|
40 ui::DragDropTypes::DRAG_MOVE
|
41 ui::DragDropTypes::DRAG_LINK
;
42 views::Widget
* widget
= views::Widget::GetWidgetForNativeView(view
);
45 widget
->RunShellDrag(NULL
, data
, gfx::Point(), operation
, source
);
47 // We hit this case when we're using WebContentsViewWin or
48 // WebContentsViewAura, instead of WebContentsViewViews.
49 views::RunShellDrag(view
, data
, gfx::Point(), operation
, source
);
52 base::MessageLoop::current()->SetNestableTasksAllowed(was_nested
);
55 int GetBookmarkDragOperation(content::BrowserContext
* browser_context
,
56 const BookmarkNode
* node
) {
57 PrefService
* prefs
= user_prefs::UserPrefs::Get(browser_context
);
59 int move
= ui::DragDropTypes::DRAG_MOVE
;
60 if (!prefs
->GetBoolean(prefs::kEditBookmarksEnabled
))
61 move
= ui::DragDropTypes::DRAG_NONE
;
63 return ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_LINK
| move
;
64 return ui::DragDropTypes::DRAG_COPY
| move
;
67 int GetPreferredBookmarkDropOperation(int source_operations
, int operations
) {
68 int common_ops
= (source_operations
& operations
);
70 return ui::DragDropTypes::DRAG_NONE
;
71 if (ui::DragDropTypes::DRAG_COPY
& common_ops
)
72 return ui::DragDropTypes::DRAG_COPY
;
73 if (ui::DragDropTypes::DRAG_LINK
& common_ops
)
74 return ui::DragDropTypes::DRAG_LINK
;
75 if (ui::DragDropTypes::DRAG_MOVE
& common_ops
)
76 return ui::DragDropTypes::DRAG_MOVE
;
77 return ui::DragDropTypes::DRAG_NONE
;
80 int GetBookmarkDropOperation(Profile
* profile
,
81 const ui::DropTargetEvent
& event
,
82 const BookmarkNodeData
& data
,
83 const BookmarkNode
* parent
,
85 const base::FilePath
& profile_path
= profile
->GetPath();
87 if (data
.IsFromProfilePath(profile_path
) && data
.size() > 1)
88 // Currently only accept one dragged node at a time.
89 return ui::DragDropTypes::DRAG_NONE
;
91 if (!IsValidBookmarkDropLocation(profile
, data
, parent
, index
))
92 return ui::DragDropTypes::DRAG_NONE
;
94 if (data
.GetFirstNode(BookmarkModelFactory::GetForProfile(profile
),
96 // User is dragging from this profile: move.
97 return ui::DragDropTypes::DRAG_MOVE
;
99 // User is dragging from another app, copy.
100 return GetPreferredBookmarkDropOperation(event
.source_operations(),
101 ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_LINK
);
104 bool IsValidBookmarkDropLocation(Profile
* profile
,
105 const BookmarkNodeData
& data
,
106 const BookmarkNode
* drop_parent
,
108 if (!drop_parent
->is_folder()) {
113 if (!data
.is_valid())
116 const base::FilePath
& profile_path
= profile
->GetPath();
117 if (data
.IsFromProfilePath(profile_path
)) {
118 std::vector
<const BookmarkNode
*> nodes
= data
.GetNodes(
119 BookmarkModelFactory::GetForProfile(profile
), profile_path
);
120 for (size_t i
= 0; i
< nodes
.size(); ++i
) {
121 // Don't allow the drop if the user is attempting to drop on one of the
122 // nodes being dragged.
123 const BookmarkNode
* node
= nodes
[i
];
124 int node_index
= (drop_parent
== node
->parent()) ?
125 drop_parent
->GetIndexOf(nodes
[i
]) : -1;
126 if (node_index
!= -1 && (index
== node_index
|| index
== node_index
+ 1))
129 // drop_parent can't accept a child that is an ancestor.
130 if (drop_parent
->HasAncestor(node
))
135 // From the same profile, always accept.
139 } // namespace chrome