| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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. | |
| 4 | |
| 5 #include "web/WebFrameWidgetBase.h" | |
| 6 | |
| 7 #include "core/dom/DocumentUserGestureToken.h" | |
| 8 #include "core/events/WebInputEventConversion.h" | |
| 9 #include "core/exported/WebViewBase.h" | |
| 10 #include "core/frame/FrameView.h" | |
| 11 #include "core/frame/VisualViewport.h" | |
| 12 #include "core/frame/WebLocalFrameBase.h" | |
| 13 #include "core/input/EventHandler.h" | |
| 14 #include "core/page/DragActions.h" | |
| 15 #include "core/page/DragController.h" | |
| 16 #include "core/page/DragData.h" | |
| 17 #include "core/page/DragSession.h" | |
| 18 #include "core/page/Page.h" | |
| 19 #include "core/page/PointerLockController.h" | |
| 20 #include "platform/UserGestureIndicator.h" | |
| 21 #include "public/web/WebWidgetClient.h" | |
| 22 | |
| 23 namespace blink { | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 // Helper to get LocalFrame* from WebLocalFrame*. | |
| 28 // TODO(dcheng): This should be moved into WebLocalFrame. | |
| 29 LocalFrame* ToCoreFrame(WebLocalFrame* frame) { | |
| 30 return ToWebLocalFrameBase(frame)->GetFrame(); | |
| 31 } | |
| 32 | |
| 33 } // namespace | |
| 34 | |
| 35 // Ensure that the WebDragOperation enum values stay in sync with the original | |
| 36 // DragOperation constants. | |
| 37 #define STATIC_ASSERT_ENUM(a, b) \ | |
| 38 static_assert(static_cast<int>(a) == static_cast<int>(b), \ | |
| 39 "mismatching enum : " #a) | |
| 40 STATIC_ASSERT_ENUM(kDragOperationNone, kWebDragOperationNone); | |
| 41 STATIC_ASSERT_ENUM(kDragOperationCopy, kWebDragOperationCopy); | |
| 42 STATIC_ASSERT_ENUM(kDragOperationLink, kWebDragOperationLink); | |
| 43 STATIC_ASSERT_ENUM(kDragOperationGeneric, kWebDragOperationGeneric); | |
| 44 STATIC_ASSERT_ENUM(kDragOperationPrivate, kWebDragOperationPrivate); | |
| 45 STATIC_ASSERT_ENUM(kDragOperationMove, kWebDragOperationMove); | |
| 46 STATIC_ASSERT_ENUM(kDragOperationDelete, kWebDragOperationDelete); | |
| 47 STATIC_ASSERT_ENUM(kDragOperationEvery, kWebDragOperationEvery); | |
| 48 | |
| 49 bool WebFrameWidgetBase::ignore_input_events_ = false; | |
| 50 | |
| 51 WebDragOperation WebFrameWidgetBase::DragTargetDragEnter( | |
| 52 const WebDragData& web_drag_data, | |
| 53 const WebPoint& point_in_viewport, | |
| 54 const WebPoint& screen_point, | |
| 55 WebDragOperationsMask operations_allowed, | |
| 56 int modifiers) { | |
| 57 DCHECK(!current_drag_data_); | |
| 58 | |
| 59 current_drag_data_ = DataObject::Create(web_drag_data); | |
| 60 operations_allowed_ = operations_allowed; | |
| 61 | |
| 62 return DragTargetDragEnterOrOver(point_in_viewport, screen_point, kDragEnter, | |
| 63 modifiers); | |
| 64 } | |
| 65 | |
| 66 WebDragOperation WebFrameWidgetBase::DragTargetDragOver( | |
| 67 const WebPoint& point_in_viewport, | |
| 68 const WebPoint& screen_point, | |
| 69 WebDragOperationsMask operations_allowed, | |
| 70 int modifiers) { | |
| 71 operations_allowed_ = operations_allowed; | |
| 72 | |
| 73 return DragTargetDragEnterOrOver(point_in_viewport, screen_point, kDragOver, | |
| 74 modifiers); | |
| 75 } | |
| 76 | |
| 77 void WebFrameWidgetBase::DragTargetDragLeave(const WebPoint& point_in_viewport, | |
| 78 const WebPoint& screen_point) { | |
| 79 DCHECK(current_drag_data_); | |
| 80 | |
| 81 // TODO(paulmeyer): It shouldn't be possible for |m_currentDragData| to be | |
| 82 // null here, but this is somehow happening (rarely). This suggests that in | |
| 83 // some cases drag-leave is happening before drag-enter, which should be | |
| 84 // impossible. This needs to be investigated further. Once fixed, the extra | |
| 85 // check for |!m_currentDragData| should be removed. (crbug.com/671152) | |
| 86 if (IgnoreInputEvents() || !current_drag_data_) { | |
| 87 CancelDrag(); | |
| 88 return; | |
| 89 } | |
| 90 | |
| 91 WebPoint point_in_root_frame(ViewportToRootFrame(point_in_viewport)); | |
| 92 DragData drag_data(current_drag_data_.Get(), point_in_root_frame, | |
| 93 screen_point, | |
| 94 static_cast<DragOperation>(operations_allowed_)); | |
| 95 | |
| 96 GetPage()->GetDragController().DragExited(&drag_data, | |
| 97 *ToCoreFrame(LocalRoot())); | |
| 98 | |
| 99 // FIXME: why is the drag scroll timer not stopped here? | |
| 100 | |
| 101 drag_operation_ = kWebDragOperationNone; | |
| 102 current_drag_data_ = nullptr; | |
| 103 } | |
| 104 | |
| 105 void WebFrameWidgetBase::DragTargetDrop(const WebDragData& web_drag_data, | |
| 106 const WebPoint& point_in_viewport, | |
| 107 const WebPoint& screen_point, | |
| 108 int modifiers) { | |
| 109 WebPoint point_in_root_frame(ViewportToRootFrame(point_in_viewport)); | |
| 110 | |
| 111 DCHECK(current_drag_data_); | |
| 112 current_drag_data_ = DataObject::Create(web_drag_data); | |
| 113 | |
| 114 // If this webview transitions from the "drop accepting" state to the "not | |
| 115 // accepting" state, then our IPC message reply indicating that may be in- | |
| 116 // flight, or else delayed by javascript processing in this webview. If a | |
| 117 // drop happens before our IPC reply has reached the browser process, then | |
| 118 // the browser forwards the drop to this webview. So only allow a drop to | |
| 119 // proceed if our webview m_dragOperation state is not DragOperationNone. | |
| 120 | |
| 121 if (drag_operation_ == kWebDragOperationNone) { | |
| 122 // IPC RACE CONDITION: do not allow this drop. | |
| 123 DragTargetDragLeave(point_in_viewport, screen_point); | |
| 124 return; | |
| 125 } | |
| 126 | |
| 127 if (!IgnoreInputEvents()) { | |
| 128 current_drag_data_->SetModifiers(modifiers); | |
| 129 DragData drag_data(current_drag_data_.Get(), point_in_root_frame, | |
| 130 screen_point, | |
| 131 static_cast<DragOperation>(operations_allowed_)); | |
| 132 | |
| 133 GetPage()->GetDragController().PerformDrag(&drag_data, | |
| 134 *ToCoreFrame(LocalRoot())); | |
| 135 } | |
| 136 drag_operation_ = kWebDragOperationNone; | |
| 137 current_drag_data_ = nullptr; | |
| 138 } | |
| 139 | |
| 140 void WebFrameWidgetBase::DragSourceEndedAt(const WebPoint& point_in_viewport, | |
| 141 const WebPoint& screen_point, | |
| 142 WebDragOperation operation) { | |
| 143 if (IgnoreInputEvents()) { | |
| 144 CancelDrag(); | |
| 145 return; | |
| 146 } | |
| 147 WebFloatPoint point_in_root_frame( | |
| 148 GetPage()->GetVisualViewport().ViewportToRootFrame(point_in_viewport)); | |
| 149 | |
| 150 WebMouseEvent fake_mouse_move(WebInputEvent::kMouseMove, point_in_root_frame, | |
| 151 WebFloatPoint(screen_point.x, screen_point.y), | |
| 152 WebPointerProperties::Button::kLeft, 0, | |
| 153 WebInputEvent::kNoModifiers, | |
| 154 TimeTicks::Now().InSeconds()); | |
| 155 fake_mouse_move.SetFrameScale(1); | |
| 156 ToCoreFrame(LocalRoot()) | |
| 157 ->GetEventHandler() | |
| 158 .DragSourceEndedAt(fake_mouse_move, | |
| 159 static_cast<DragOperation>(operation)); | |
| 160 } | |
| 161 | |
| 162 void WebFrameWidgetBase::DragSourceSystemDragEnded() { | |
| 163 CancelDrag(); | |
| 164 } | |
| 165 | |
| 166 void WebFrameWidgetBase::CancelDrag() { | |
| 167 // It's possible for us this to be callback while we're not doing a drag if | |
| 168 // it's from a previous page that got unloaded. | |
| 169 if (!doing_drag_and_drop_) | |
| 170 return; | |
| 171 GetPage()->GetDragController().DragEnded(); | |
| 172 doing_drag_and_drop_ = false; | |
| 173 } | |
| 174 | |
| 175 void WebFrameWidgetBase::StartDragging(WebReferrerPolicy policy, | |
| 176 const WebDragData& data, | |
| 177 WebDragOperationsMask mask, | |
| 178 const WebImage& drag_image, | |
| 179 const WebPoint& drag_image_offset) { | |
| 180 doing_drag_and_drop_ = true; | |
| 181 Client()->StartDragging(policy, data, mask, drag_image, drag_image_offset); | |
| 182 } | |
| 183 | |
| 184 WebDragOperation WebFrameWidgetBase::DragTargetDragEnterOrOver( | |
| 185 const WebPoint& point_in_viewport, | |
| 186 const WebPoint& screen_point, | |
| 187 DragAction drag_action, | |
| 188 int modifiers) { | |
| 189 DCHECK(current_drag_data_); | |
| 190 // TODO(paulmeyer): It shouldn't be possible for |m_currentDragData| to be | |
| 191 // null here, but this is somehow happening (rarely). This suggests that in | |
| 192 // some cases drag-over is happening before drag-enter, which should be | |
| 193 // impossible. This needs to be investigated further. Once fixed, the extra | |
| 194 // check for |!m_currentDragData| should be removed. (crbug.com/671504) | |
| 195 if (IgnoreInputEvents() || !current_drag_data_) { | |
| 196 CancelDrag(); | |
| 197 return kWebDragOperationNone; | |
| 198 } | |
| 199 | |
| 200 WebPoint point_in_root_frame(ViewportToRootFrame(point_in_viewport)); | |
| 201 | |
| 202 current_drag_data_->SetModifiers(modifiers); | |
| 203 DragData drag_data(current_drag_data_.Get(), point_in_root_frame, | |
| 204 screen_point, | |
| 205 static_cast<DragOperation>(operations_allowed_)); | |
| 206 | |
| 207 DragSession drag_session; | |
| 208 drag_session = GetPage()->GetDragController().DragEnteredOrUpdated( | |
| 209 &drag_data, *ToCoreFrame(LocalRoot())); | |
| 210 | |
| 211 DragOperation drop_effect = drag_session.operation; | |
| 212 | |
| 213 // Mask the drop effect operation against the drag source's allowed | |
| 214 // operations. | |
| 215 if (!(drop_effect & drag_data.DraggingSourceOperationMask())) | |
| 216 drop_effect = kDragOperationNone; | |
| 217 | |
| 218 drag_operation_ = static_cast<WebDragOperation>(drop_effect); | |
| 219 | |
| 220 return drag_operation_; | |
| 221 } | |
| 222 | |
| 223 WebPoint WebFrameWidgetBase::ViewportToRootFrame( | |
| 224 const WebPoint& point_in_viewport) const { | |
| 225 return GetPage()->GetVisualViewport().ViewportToRootFrame(point_in_viewport); | |
| 226 } | |
| 227 | |
| 228 WebViewBase* WebFrameWidgetBase::View() const { | |
| 229 return ToWebLocalFrameBase(LocalRoot())->ViewImpl(); | |
| 230 } | |
| 231 | |
| 232 Page* WebFrameWidgetBase::GetPage() const { | |
| 233 return View()->GetPage(); | |
| 234 } | |
| 235 | |
| 236 void WebFrameWidgetBase::DidAcquirePointerLock() { | |
| 237 GetPage()->GetPointerLockController().DidAcquirePointerLock(); | |
| 238 } | |
| 239 | |
| 240 void WebFrameWidgetBase::DidNotAcquirePointerLock() { | |
| 241 GetPage()->GetPointerLockController().DidNotAcquirePointerLock(); | |
| 242 } | |
| 243 | |
| 244 void WebFrameWidgetBase::DidLosePointerLock() { | |
| 245 pointer_lock_gesture_token_.Clear(); | |
| 246 GetPage()->GetPointerLockController().DidLosePointerLock(); | |
| 247 } | |
| 248 | |
| 249 void WebFrameWidgetBase::PointerLockMouseEvent(const WebInputEvent& event) { | |
| 250 std::unique_ptr<UserGestureIndicator> gesture_indicator; | |
| 251 AtomicString event_type; | |
| 252 switch (event.GetType()) { | |
| 253 case WebInputEvent::kMouseDown: | |
| 254 event_type = EventTypeNames::mousedown; | |
| 255 if (!GetPage() || !GetPage()->GetPointerLockController().GetElement()) | |
| 256 break; | |
| 257 gesture_indicator = WTF::WrapUnique(new UserGestureIndicator( | |
| 258 DocumentUserGestureToken::Create(&GetPage() | |
| 259 ->GetPointerLockController() | |
| 260 .GetElement() | |
| 261 ->GetDocument(), | |
| 262 UserGestureToken::kNewGesture))); | |
| 263 pointer_lock_gesture_token_ = gesture_indicator->CurrentToken(); | |
| 264 break; | |
| 265 case WebInputEvent::kMouseUp: | |
| 266 event_type = EventTypeNames::mouseup; | |
| 267 gesture_indicator = WTF::WrapUnique( | |
| 268 new UserGestureIndicator(pointer_lock_gesture_token_.Release())); | |
| 269 break; | |
| 270 case WebInputEvent::kMouseMove: | |
| 271 event_type = EventTypeNames::mousemove; | |
| 272 break; | |
| 273 default: | |
| 274 NOTREACHED(); | |
| 275 } | |
| 276 | |
| 277 const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event); | |
| 278 | |
| 279 if (GetPage()) { | |
| 280 WebMouseEvent transformed_event = TransformWebMouseEvent( | |
| 281 ToWebLocalFrameBase(LocalRoot())->GetFrameView(), mouse_event); | |
| 282 GetPage()->GetPointerLockController().DispatchLockedMouseEvent( | |
| 283 transformed_event, event_type); | |
| 284 } | |
| 285 } | |
| 286 | |
| 287 } // namespace blink | |
| OLD | NEW |