| OLD | NEW |
| 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 "content/browser/web_contents/web_drag_dest_mac.h" | 5 #import "content/browser/web_contents/web_drag_dest_mac.h" |
| 6 | 6 |
| 7 #import <Carbon/Carbon.h> | 7 #import <Carbon/Carbon.h> |
| 8 | 8 |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #include "content/browser/renderer_host/render_view_host_impl.h" | 10 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 11 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 12 #include "content/browser/renderer_host/render_widget_host_input_event_router.h" |
| 11 #include "content/browser/web_contents/web_contents_impl.h" | 13 #include "content/browser/web_contents/web_contents_impl.h" |
| 12 #include "content/public/browser/web_contents_delegate.h" | 14 #include "content/public/browser/web_contents_delegate.h" |
| 13 #include "content/public/browser/web_drag_dest_delegate.h" | 15 #include "content/public/browser/web_drag_dest_delegate.h" |
| 14 #include "content/public/common/drop_data.h" | 16 #include "content/public/common/drop_data.h" |
| 15 #include "third_party/WebKit/public/platform/WebInputEvent.h" | 17 #include "third_party/WebKit/public/platform/WebInputEvent.h" |
| 16 #import "third_party/mozilla/NSPasteboard+Utils.h" | 18 #import "third_party/mozilla/NSPasteboard+Utils.h" |
| 17 #include "ui/base/clipboard/custom_data_helper.h" | 19 #include "ui/base/clipboard/custom_data_helper.h" |
| 18 #include "ui/base/cocoa/cocoa_base_utils.h" | 20 #include "ui/base/cocoa/cocoa_base_utils.h" |
| 19 #import "ui/base/dragdrop/cocoa_dnd_util.h" | 21 #import "ui/base/dragdrop/cocoa_dnd_util.h" |
| 20 #include "ui/base/window_open_disposition.h" | 22 #include "ui/base/window_open_disposition.h" |
| 23 #include "ui/gfx/geometry/point.h" |
| 21 | 24 |
| 22 using blink::WebDragOperationsMask; | 25 using blink::WebDragOperationsMask; |
| 23 using content::DropData; | 26 using content::DropData; |
| 24 using content::OpenURLParams; | 27 using content::OpenURLParams; |
| 25 using content::Referrer; | 28 using content::Referrer; |
| 26 using content::WebContentsImpl; | 29 using content::WebContentsImpl; |
| 27 | 30 |
| 28 namespace { | 31 namespace { |
| 29 | 32 |
| 30 int GetModifierFlags() { | 33 int GetModifierFlags() { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 121 |
| 119 // Messages to send during the tracking of a drag, usually upon receiving | 122 // Messages to send during the tracking of a drag, usually upon receiving |
| 120 // calls from the view system. Communicates the drag messages to WebCore. | 123 // calls from the view system. Communicates the drag messages to WebCore. |
| 121 | 124 |
| 122 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info | 125 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info |
| 123 view:(NSView*)view { | 126 view:(NSView*)view { |
| 124 // Save off the RVH so we can tell if it changes during a drag. If it does, | 127 // Save off the RVH so we can tell if it changes during a drag. If it does, |
| 125 // we need to send a new enter message in draggingUpdated:. | 128 // we need to send a new enter message in draggingUpdated:. |
| 126 currentRVH_ = webContents_->GetRenderViewHost(); | 129 currentRVH_ = webContents_->GetRenderViewHost(); |
| 127 | 130 |
| 131 // Create the appropriate mouse locations for WebCore. The draggingLocation |
| 132 // is in window coordinates. Both need to be flipped. |
| 133 NSPoint windowPoint = [info draggingLocation]; |
| 134 NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view]; |
| 135 NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view]; |
| 136 gfx::Point transformedPt; |
| 137 currentRWHForDrag_ = |
| 138 [self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt] |
| 139 ->GetWeakPtr(); |
| 140 |
| 128 // Fill out a DropData from pasteboard. | 141 // Fill out a DropData from pasteboard. |
| 129 std::unique_ptr<DropData> dropData; | 142 std::unique_ptr<DropData> dropData; |
| 130 dropData.reset(new DropData()); | 143 dropData.reset(new DropData()); |
| 131 [self populateDropData:dropData.get() | 144 [self populateDropData:dropData.get() |
| 132 fromPasteboard:[info draggingPasteboard]]; | 145 fromPasteboard:[info draggingPasteboard]]; |
| 133 // TODO(paulmeyer): This will need to target the correct specific | 146 // TODO(paulmeyer): Data may be pulled from the pasteboard multiple times per |
| 134 // RenderWidgetHost to work with OOPIFs. See crbug.com/647249. | 147 // drag. Ideally, this should only be done once, and filtered as needed. |
| 135 currentRVH_->GetWidget()->FilterDropData(dropData.get()); | 148 currentRWHForDrag_->FilterDropData(dropData.get()); |
| 136 | 149 |
| 137 NSDragOperation mask = [info draggingSourceOperationMask]; | 150 NSDragOperation mask = [info draggingSourceOperationMask]; |
| 138 | 151 |
| 139 // Give the delegate an opportunity to cancel the drag. | 152 // Give the delegate an opportunity to cancel the drag. |
| 140 canceled_ = !webContents_->GetDelegate()->CanDragEnter( | 153 canceled_ = !webContents_->GetDelegate()->CanDragEnter( |
| 141 webContents_, | 154 webContents_, |
| 142 *dropData, | 155 *dropData, |
| 143 static_cast<WebDragOperationsMask>(mask)); | 156 static_cast<WebDragOperationsMask>(mask)); |
| 144 if (canceled_) | 157 if (canceled_) |
| 145 return NSDragOperationNone; | 158 return NSDragOperationNone; |
| 146 | 159 |
| 147 if ([self onlyAllowsNavigation]) { | 160 if ([self onlyAllowsNavigation]) { |
| 148 if ([[info draggingPasteboard] containsURLDataConvertingTextToURL:YES]) | 161 if ([[info draggingPasteboard] containsURLDataConvertingTextToURL:YES]) |
| 149 return NSDragOperationCopy; | 162 return NSDragOperationCopy; |
| 150 return NSDragOperationNone; | 163 return NSDragOperationNone; |
| 151 } | 164 } |
| 152 | 165 |
| 153 if (delegate_) { | 166 if (delegate_) { |
| 154 delegate_->DragInitialize(webContents_); | 167 delegate_->DragInitialize(webContents_); |
| 155 delegate_->OnDragEnter(); | 168 delegate_->OnDragEnter(); |
| 156 } | 169 } |
| 157 | 170 |
| 158 dropData_.swap(dropData); | 171 dropData_.swap(dropData); |
| 159 | 172 |
| 160 // Create the appropriate mouse locations for WebCore. The draggingLocation | 173 currentRWHForDrag_->DragTargetDragEnter( |
| 161 // is in window coordinates. Both need to be flipped. | 174 *dropData_, transformedPt, gfx::Point(screenPoint.x, screenPoint.y), |
| 162 NSPoint windowPoint = [info draggingLocation]; | 175 static_cast<WebDragOperationsMask>(mask), GetModifierFlags()); |
| 163 NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view]; | |
| 164 NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view]; | |
| 165 // TODO(paulmeyer): This will need to target the correct specific | |
| 166 // RenderWidgetHost to work with OOPIFs. See crbug.com/647249. | |
| 167 webContents_->GetRenderViewHost()->GetWidget()->DragTargetDragEnter( | |
| 168 *dropData_, | |
| 169 gfx::Point(viewPoint.x, viewPoint.y), | |
| 170 gfx::Point(screenPoint.x, screenPoint.y), | |
| 171 static_cast<WebDragOperationsMask>(mask), | |
| 172 GetModifierFlags()); | |
| 173 | 176 |
| 174 // We won't know the true operation (whether the drag is allowed) until we | 177 // We won't know the true operation (whether the drag is allowed) until we |
| 175 // hear back from the renderer. For now, be optimistic: | 178 // hear back from the renderer. For now, be optimistic: |
| 176 currentOperation_ = NSDragOperationCopy; | 179 currentOperation_ = NSDragOperationCopy; |
| 177 return currentOperation_; | 180 return currentOperation_; |
| 178 } | 181 } |
| 179 | 182 |
| 180 - (void)draggingExited:(id<NSDraggingInfo>)info { | 183 - (void)draggingExited:(id<NSDraggingInfo>)info { |
| 181 DCHECK(currentRVH_); | 184 DCHECK(currentRVH_); |
| 182 if (currentRVH_ != webContents_->GetRenderViewHost()) | 185 if (currentRVH_ != webContents_->GetRenderViewHost()) |
| 183 return; | 186 return; |
| 184 | 187 |
| 185 if (canceled_) | 188 if (canceled_) |
| 186 return; | 189 return; |
| 187 | 190 |
| 188 if ([self onlyAllowsNavigation]) | 191 if ([self onlyAllowsNavigation]) |
| 189 return; | 192 return; |
| 190 | 193 |
| 191 if (delegate_) | 194 if (delegate_) |
| 192 delegate_->OnDragLeave(); | 195 delegate_->OnDragLeave(); |
| 193 | 196 |
| 194 // TODO(paulmeyer): This will need to target the correct specific | 197 if (currentRWHForDrag_) { |
| 195 // RenderWidgetHost to work with OOPIFs. See crbug.com/647249. | 198 currentRWHForDrag_->DragTargetDragLeave(); |
| 196 webContents_->GetRenderViewHost()->GetWidget()->DragTargetDragLeave(); | 199 currentRWHForDrag_.reset(); |
| 200 } |
| 197 dropData_.reset(); | 201 dropData_.reset(); |
| 198 } | 202 } |
| 199 | 203 |
| 200 - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info | 204 - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info |
| 201 view:(NSView*)view { | 205 view:(NSView*)view { |
| 202 DCHECK(currentRVH_); | 206 // Create the appropriate mouse locations for WebCore. The draggingLocation |
| 203 if (currentRVH_ != webContents_->GetRenderViewHost()) | 207 // is in window coordinates. Both need to be flipped. |
| 208 NSPoint windowPoint = [info draggingLocation]; |
| 209 NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view]; |
| 210 NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view]; |
| 211 gfx::Point transformedPt; |
| 212 content::RenderWidgetHostImpl* targetRWH = |
| 213 [self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt]; |
| 214 |
| 215 // TODO(paulmeyer): The dragging delegates may now by invoked multiple times |
| 216 // per drag, even without the drag ever leaving the window. |
| 217 if (targetRWH != currentRWHForDrag_.get()) { |
| 218 if (currentRWHForDrag_) |
| 219 currentRWHForDrag_->DragTargetDragLeave(); |
| 204 [self draggingEntered:info view:view]; | 220 [self draggingEntered:info view:view]; |
| 221 } |
| 205 | 222 |
| 206 if (canceled_) | 223 if (canceled_) |
| 207 return NSDragOperationNone; | 224 return NSDragOperationNone; |
| 208 | 225 |
| 209 if ([self onlyAllowsNavigation]) { | 226 if ([self onlyAllowsNavigation]) { |
| 210 if ([[info draggingPasteboard] containsURLDataConvertingTextToURL:YES]) | 227 if ([[info draggingPasteboard] containsURLDataConvertingTextToURL:YES]) |
| 211 return NSDragOperationCopy; | 228 return NSDragOperationCopy; |
| 212 return NSDragOperationNone; | 229 return NSDragOperationNone; |
| 213 } | 230 } |
| 214 | 231 |
| 215 // Create the appropriate mouse locations for WebCore. The draggingLocation | |
| 216 // is in window coordinates. | |
| 217 NSPoint windowPoint = [info draggingLocation]; | |
| 218 NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view]; | |
| 219 NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view]; | |
| 220 NSDragOperation mask = [info draggingSourceOperationMask]; | 232 NSDragOperation mask = [info draggingSourceOperationMask]; |
| 221 // TODO(paulmeyer): This will need to target the correct specific | 233 targetRWH->DragTargetDragOver( |
| 222 // RenderWidgetHost to work with OOPIFs. See crbug.com/647249. | 234 transformedPt, gfx::Point(screenPoint.x, screenPoint.y), |
| 223 webContents_->GetRenderViewHost()->GetWidget()->DragTargetDragOver( | 235 static_cast<WebDragOperationsMask>(mask), GetModifierFlags()); |
| 224 gfx::Point(viewPoint.x, viewPoint.y), | |
| 225 gfx::Point(screenPoint.x, screenPoint.y), | |
| 226 static_cast<WebDragOperationsMask>(mask), | |
| 227 GetModifierFlags()); | |
| 228 | 236 |
| 229 if (delegate_) | 237 if (delegate_) |
| 230 delegate_->OnDragOver(); | 238 delegate_->OnDragOver(); |
| 231 | 239 |
| 232 return currentOperation_; | 240 return currentOperation_; |
| 233 } | 241 } |
| 234 | 242 |
| 235 - (BOOL)performDragOperation:(id<NSDraggingInfo>)info | 243 - (BOOL)performDragOperation:(id<NSDraggingInfo>)info |
| 236 view:(NSView*)view { | 244 view:(NSView*)view { |
| 237 if (currentRVH_ != webContents_->GetRenderViewHost()) | 245 // Create the appropriate mouse locations for WebCore. The draggingLocation |
| 246 // is in window coordinates. Both need to be flipped. |
| 247 NSPoint windowPoint = [info draggingLocation]; |
| 248 NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view]; |
| 249 NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view]; |
| 250 gfx::Point transformedPt; |
| 251 content::RenderWidgetHostImpl* targetRWH = |
| 252 [self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt]; |
| 253 |
| 254 if (targetRWH != currentRWHForDrag_.get()) { |
| 255 if (currentRWHForDrag_) |
| 256 currentRWHForDrag_->DragTargetDragLeave(); |
| 238 [self draggingEntered:info view:view]; | 257 [self draggingEntered:info view:view]; |
| 258 } |
| 239 | 259 |
| 240 // Check if we only allow navigation and navigate to a url on the pasteboard. | 260 // Check if we only allow navigation and navigate to a url on the pasteboard. |
| 241 if ([self onlyAllowsNavigation]) { | 261 if ([self onlyAllowsNavigation]) { |
| 242 NSPasteboard* pboard = [info draggingPasteboard]; | 262 NSPasteboard* pboard = [info draggingPasteboard]; |
| 243 if ([pboard containsURLDataConvertingTextToURL:YES]) { | 263 if ([pboard containsURLDataConvertingTextToURL:YES]) { |
| 244 GURL url; | 264 GURL url; |
| 245 ui::PopulateURLAndTitleFromPasteboard(&url, NULL, pboard, YES); | 265 ui::PopulateURLAndTitleFromPasteboard(&url, NULL, pboard, YES); |
| 246 webContents_->OpenURL( | 266 webContents_->OpenURL( |
| 247 OpenURLParams(url, Referrer(), WindowOpenDisposition::CURRENT_TAB, | 267 OpenURLParams(url, Referrer(), WindowOpenDisposition::CURRENT_TAB, |
| 248 ui::PAGE_TRANSITION_AUTO_BOOKMARK, false)); | 268 ui::PAGE_TRANSITION_AUTO_BOOKMARK, false)); |
| 249 return YES; | 269 return YES; |
| 250 } else { | 270 } else { |
| 251 return NO; | 271 return NO; |
| 252 } | 272 } |
| 253 } | 273 } |
| 254 | 274 |
| 255 if (delegate_) | 275 if (delegate_) |
| 256 delegate_->OnDrop(); | 276 delegate_->OnDrop(); |
| 257 | 277 |
| 258 currentRVH_ = NULL; | 278 currentRVH_ = NULL; |
| 259 | 279 |
| 260 // Create the appropriate mouse locations for WebCore. The draggingLocation | 280 targetRWH->DragTargetDrop(*dropData_, transformedPt, |
| 261 // is in window coordinates. Both need to be flipped. | 281 gfx::Point(screenPoint.x, screenPoint.y), |
| 262 NSPoint windowPoint = [info draggingLocation]; | 282 GetModifierFlags()); |
| 263 NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view]; | |
| 264 NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view]; | |
| 265 // TODO(paulmeyer): This will need to target the correct specific | |
| 266 // RenderWidgetHost to work with OOPIFs. See crbug.com/647249. | |
| 267 webContents_->GetRenderViewHost()->GetWidget()->DragTargetDrop( | |
| 268 *dropData_, gfx::Point(viewPoint.x, viewPoint.y), | |
| 269 gfx::Point(screenPoint.x, screenPoint.y), GetModifierFlags()); | |
| 270 | 283 |
| 271 dropData_.reset(); | 284 dropData_.reset(); |
| 272 | 285 |
| 273 return YES; | 286 return YES; |
| 274 } | 287 } |
| 275 | 288 |
| 289 - (content::RenderWidgetHostImpl*) |
| 290 GetRenderWidgetHostAtPoint:(const NSPoint&)viewPoint |
| 291 transformedPt:(gfx::Point*)transformedPt { |
| 292 return webContents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint( |
| 293 webContents_->GetRenderViewHost()->GetWidget()->GetView(), |
| 294 gfx::Point(viewPoint.x, viewPoint.y), transformedPt); |
| 295 } |
| 296 |
| 276 // Given |data|, which should not be nil, fill it in using the contents of the | 297 // Given |data|, which should not be nil, fill it in using the contents of the |
| 277 // given pasteboard. The types handled by this method should be kept in sync | 298 // given pasteboard. The types handled by this method should be kept in sync |
| 278 // with [WebContentsViewCocoa registerDragTypes]. | 299 // with [WebContentsViewCocoa registerDragTypes]. |
| 279 - (void)populateDropData:(DropData*)data | 300 - (void)populateDropData:(DropData*)data |
| 280 fromPasteboard:(NSPasteboard*)pboard { | 301 fromPasteboard:(NSPasteboard*)pboard { |
| 281 DCHECK(data); | 302 DCHECK(data); |
| 282 DCHECK(pboard); | 303 DCHECK(pboard); |
| 283 NSArray* types = [pboard types]; | 304 NSArray* types = [pboard types]; |
| 284 | 305 |
| 285 data->did_originate_from_renderer = | 306 data->did_originate_from_renderer = |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 // Get custom MIME data. | 354 // Get custom MIME data. |
| 334 if ([types containsObject:ui::kWebCustomDataPboardType]) { | 355 if ([types containsObject:ui::kWebCustomDataPboardType]) { |
| 335 NSData* customData = [pboard dataForType:ui::kWebCustomDataPboardType]; | 356 NSData* customData = [pboard dataForType:ui::kWebCustomDataPboardType]; |
| 336 ui::ReadCustomDataIntoMap([customData bytes], | 357 ui::ReadCustomDataIntoMap([customData bytes], |
| 337 [customData length], | 358 [customData length], |
| 338 &data->custom_data); | 359 &data->custom_data); |
| 339 } | 360 } |
| 340 } | 361 } |
| 341 | 362 |
| 342 @end | 363 @end |
| OLD | NEW |