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. 4 5 #ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_AURA_H_ 6 #define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_AURA_H_ 7 8 #include <memory> 9 #include <utility> 10 #include <vector> 11 12 #include "base/callback_helpers.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/macros.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/optional.h" 18 #include "build/build_config.h" 19 #include "content/browser/renderer_host/render_view_host_delegate_view.h" 20 #include "content/browser/web_contents/web_contents_view.h" 21 #include "content/common/buildflags.h" 22 #include "content/common/content_export.h" 23 #include "content/public/browser/global_routing_id.h" 24 #include "content/public/browser/visibility.h" 25 #include "content/public/browser/web_contents_view_delegate.h" 26 #include "content/public/common/drop_data.h" 27 #include "ui/aura/client/drag_drop_delegate.h" 28 #include "ui/aura/window.h" 29 #include "ui/aura/window_delegate.h" 30 #include "ui/base/dragdrop/drop_target_event.h" 31 32 namespace ui { 33 class DropTargetEvent; 34 class TouchSelectionController; 35 } 36 37 namespace content { 38 class GestureNavSimple; 39 class RenderWidgetHostImpl; 40 class RenderWidgetHostViewAura; 41 class TouchSelectionControllerClientAura; 42 class WebContentsImpl; 43 class WebDragDestDelegate; 44 45 class CONTENT_EXPORT WebContentsViewAura 46 : public WebContentsView, 47 public RenderViewHostDelegateView, 48 public aura::WindowDelegate, 49 public aura::client::DragDropDelegate { 50 public: 51 WebContentsViewAura(WebContentsImpl* web_contents, 52 WebContentsViewDelegate* delegate); 53 54 // Allow the WebContentsViewDelegate to be set explicitly. 55 void SetDelegateForTesting(WebContentsViewDelegate* delegate); 56 57 // Set a flag to pass nullptr as the parent_view argument to 58 // RenderWidgetHostViewAura::InitAsChild(). set_init_rwhv_with_null_parent_for_testing(bool set)59 void set_init_rwhv_with_null_parent_for_testing(bool set) { 60 init_rwhv_with_null_parent_for_testing_ = set; 61 } 62 63 using RenderWidgetHostViewCreateFunction = 64 RenderWidgetHostViewAura* (*)(RenderWidgetHost*); 65 66 // Used to override the creation of RenderWidgetHostViews in tests. 67 static void InstallCreateHookForTests( 68 RenderWidgetHostViewCreateFunction create_render_widget_host_view); 69 70 private: 71 // A structure used to keep drop context for asynchronously finishing a 72 // drop operation. This is required because some drop event data gets 73 // cleared out once PerformDropCallback() returns. 74 struct CONTENT_EXPORT OnPerformDropContext { 75 OnPerformDropContext(RenderWidgetHostImpl* target_rwh, 76 const ui::DropTargetEvent& event, 77 std::unique_ptr<ui::OSExchangeData> data, 78 base::ScopedClosureRunner end_drag_runner, 79 base::Optional<gfx::PointF> transformed_pt, 80 gfx::PointF screen_pt); 81 OnPerformDropContext(OnPerformDropContext&& other); 82 ~OnPerformDropContext(); 83 84 base::WeakPtr<RenderWidgetHostImpl> target_rwh; 85 ui::DropTargetEvent event; 86 std::unique_ptr<ui::OSExchangeData> data; 87 base::ScopedClosureRunner end_drag_runner; 88 base::Optional<gfx::PointF> transformed_pt; 89 gfx::PointF screen_pt; 90 }; 91 92 friend class WebContentsViewAuraTest; 93 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, EnableDisableOverscroll); 94 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropFiles); 95 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, 96 DragDropFilesOriginateFromRenderer); 97 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropVirtualFiles); 98 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, 99 DragDropVirtualFilesOriginateFromRenderer); 100 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropUrlData); 101 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropOnOopif); 102 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, OnPerformDrop_DeepScanOK); 103 FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, OnPerformDrop_DeepScanBad); 104 105 class WindowObserver; 106 107 ~WebContentsViewAura() override; 108 109 void SizeChangedCommon(const gfx::Size& size); 110 111 void EndDrag(base::WeakPtr<RenderWidgetHostImpl> source_rwh_weak_ptr, 112 blink::WebDragOperationsMask ops); 113 114 void InstallOverscrollControllerDelegate(RenderWidgetHostViewAura* view); 115 116 ui::TouchSelectionController* GetSelectionController() const; 117 TouchSelectionControllerClientAura* GetSelectionControllerClient() const; 118 119 // Returns GetNativeView unless overridden for testing. 120 gfx::NativeView GetRenderWidgetHostViewParent() const; 121 122 // Returns whether |target_rwh| is a valid RenderWidgetHost to be dragging 123 // over. This enforces that same-page, cross-site drags are not allowed. See 124 // crbug.com/666858. 125 bool IsValidDragTarget(RenderWidgetHostImpl* target_rwh) const; 126 127 // Called from CreateView() to create |window_|. 128 void CreateAuraWindow(aura::Window* context); 129 130 // Computes the view's visibility updates the WebContents accordingly. 131 void UpdateWebContentsVisibility(); 132 133 // Computes the view's visibility. 134 Visibility GetVisibility() const; 135 136 // Overridden from WebContentsView: 137 gfx::NativeView GetNativeView() const override; 138 gfx::NativeView GetContentNativeView() const override; 139 gfx::NativeWindow GetTopLevelNativeWindow() const override; 140 void GetContainerBounds(gfx::Rect* out) const override; 141 void SizeContents(const gfx::Size& size) override; 142 void Focus() override; 143 void SetInitialFocus() override; 144 void StoreFocus() override; 145 void RestoreFocus() override; 146 void FocusThroughTabTraversal(bool reverse) override; 147 DropData* GetDropData() const override; 148 gfx::Rect GetViewBounds() const override; 149 void CreateView(gfx::NativeView context) override; 150 RenderWidgetHostViewBase* CreateViewForWidget( 151 RenderWidgetHost* render_widget_host) override; 152 RenderWidgetHostViewBase* CreateViewForChildWidget( 153 RenderWidgetHost* render_widget_host) override; 154 void SetPageTitle(const base::string16& title) override; 155 void RenderViewReady() override; 156 void RenderViewHostChanged(RenderViewHost* old_host, 157 RenderViewHost* new_host) override; 158 void SetOverscrollControllerEnabled(bool enabled) override; 159 160 // Overridden from RenderViewHostDelegateView: 161 void ShowContextMenu(RenderFrameHost* render_frame_host, 162 const ContextMenuParams& params) override; 163 void StartDragging(const DropData& drop_data, 164 blink::WebDragOperationsMask operations, 165 const gfx::ImageSkia& image, 166 const gfx::Vector2d& image_offset, 167 const DragEventSourceInfo& event_info, 168 RenderWidgetHostImpl* source_rwh) override; 169 void UpdateDragCursor(blink::WebDragOperation operation) override; 170 void GotFocus(RenderWidgetHostImpl* render_widget_host) override; 171 void LostFocus(RenderWidgetHostImpl* render_widget_host) override; 172 void TakeFocus(bool reverse) override; 173 int GetTopControlsHeight() const override; 174 int GetBottomControlsHeight() const override; 175 bool DoBrowserControlsShrinkRendererSize() const override; 176 #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) 177 void ShowPopupMenu(RenderFrameHost* render_frame_host, 178 const gfx::Rect& bounds, 179 int item_height, 180 double item_font_size, 181 int selected_item, 182 const std::vector<MenuItem>& items, 183 bool right_aligned, 184 bool allow_multiple_selection) override; 185 186 void HidePopupMenu() override; 187 #endif 188 189 // Overridden from aura::WindowDelegate: 190 gfx::Size GetMinimumSize() const override; 191 gfx::Size GetMaximumSize() const override; 192 void OnBoundsChanged(const gfx::Rect& old_bounds, 193 const gfx::Rect& new_bounds) override; 194 gfx::NativeCursor GetCursor(const gfx::Point& point) override; 195 int GetNonClientComponent(const gfx::Point& point) const override; 196 bool ShouldDescendIntoChildForEventHandling( 197 aura::Window* child, 198 const gfx::Point& location) override; 199 bool CanFocus() override; 200 void OnCaptureLost() override; 201 void OnPaint(const ui::PaintContext& context) override; 202 void OnDeviceScaleFactorChanged(float old_device_scale_factor, 203 float new_device_scale_factor) override; 204 void OnWindowDestroying(aura::Window* window) override; 205 void OnWindowDestroyed(aura::Window* window) override; 206 void OnWindowTargetVisibilityChanged(bool visible) override; 207 void OnWindowOcclusionChanged(aura::Window::OcclusionState occlusion_state, 208 const SkRegion&) override; 209 bool HasHitTestMask() const override; 210 void GetHitTestMask(SkPath* mask) const override; 211 212 // Overridden from ui::EventHandler: 213 void OnKeyEvent(ui::KeyEvent* event) override; 214 void OnMouseEvent(ui::MouseEvent* event) override; 215 216 // Overridden from aura::client::DragDropDelegate: 217 void OnDragEntered(const ui::DropTargetEvent& event) override; 218 int OnDragUpdated(const ui::DropTargetEvent& event) override; 219 void OnDragExited() override; 220 int OnPerformDrop(const ui::DropTargetEvent& event, 221 std::unique_ptr<ui::OSExchangeData> data) override; 222 void DragEnteredCallback(ui::DropTargetEvent event, 223 std::unique_ptr<DropData> drop_data, 224 base::WeakPtr<RenderWidgetHostViewBase> target, 225 base::Optional<gfx::PointF> transformed_pt); 226 void DragUpdatedCallback(ui::DropTargetEvent event, 227 std::unique_ptr<DropData> drop_data, 228 base::WeakPtr<RenderWidgetHostViewBase> target, 229 base::Optional<gfx::PointF> transformed_pt); 230 void PerformDropCallback(ui::DropTargetEvent event, 231 std::unique_ptr<ui::OSExchangeData> data, 232 base::WeakPtr<RenderWidgetHostViewBase> target, 233 base::Optional<gfx::PointF> transformed_pt); 234 235 // Completes a drag exit operation by communicating with the renderer process. 236 void CompleteDragExit(); 237 238 // Called from PerformDropCallback() to finish processing the drop. 239 void FinishOnPerformDropCallback( 240 OnPerformDropContext context, 241 WebContentsViewDelegate::DropCompletionResult result); 242 243 // Completes a drop operation by communicating the drop data to the renderer 244 // process. 245 void CompleteDrop(RenderWidgetHostImpl* target_rwh, 246 const DropData& drop_data, 247 const gfx::PointF& client_pt, 248 const gfx::PointF& screen_pt, 249 int key_modifiers); 250 251 // For unit testing, registers a callback for when a drop operation 252 // completes. 253 using DropCallbackForTesting = 254 base::OnceCallback<void(RenderWidgetHostImpl* target_rwh, 255 const DropData& drop_data, 256 const gfx::PointF& client_pt, 257 const gfx::PointF& screen_pt, 258 int key_modifiers, 259 bool drop_allowed)>; 260 void RegisterDropCallbackForTesting(DropCallbackForTesting callback); 261 SetDragDestDelegateForTesting(WebDragDestDelegate * delegate)262 void SetDragDestDelegateForTesting(WebDragDestDelegate* delegate) { 263 drag_dest_delegate_ = delegate; 264 } 265 266 #if defined(OS_WIN) 267 // Callback for asynchronous retrieval of virtual files. 268 void OnGotVirtualFilesAsTempFiles( 269 const std::vector<std::pair</*temp path*/ base::FilePath, 270 /*display name*/ base::FilePath>>& 271 filepaths_and_names); 272 273 class AsyncDropNavigationObserver; 274 std::unique_ptr<AsyncDropNavigationObserver> async_drop_navigation_observer_; 275 276 class AsyncDropTempFileDeleter; 277 std::unique_ptr<AsyncDropTempFileDeleter> async_drop_temp_file_deleter_; 278 #endif 279 DropCallbackForTesting drop_callback_for_testing_; 280 281 // If this callback is initialized it must be run after the drop operation is 282 // done to send dragend event in EndDrag function. 283 base::ScopedClosureRunner end_drag_runner_; 284 285 std::unique_ptr<aura::Window> window_; 286 287 std::unique_ptr<WindowObserver> window_observer_; 288 289 // The WebContentsImpl whose contents we display. 290 WebContentsImpl* web_contents_; 291 292 std::unique_ptr<WebContentsViewDelegate> delegate_; 293 294 blink::WebDragOperationsMask current_drag_op_; 295 296 std::unique_ptr<DropData> current_drop_data_; 297 298 WebDragDestDelegate* drag_dest_delegate_; 299 300 // We keep track of the RenderWidgetHost we're dragging over. If it changes 301 // during a drag, we need to re-send the DragEnter message. 302 base::WeakPtr<RenderWidgetHostImpl> current_rwh_for_drag_; 303 304 // We also keep track of the ID of the RenderViewHost we're dragging over to 305 // avoid sending the drag exited message after leaving the current view. 306 GlobalRoutingID current_rvh_for_drag_; 307 308 // We track the IDs of the source RenderProcessHost and RenderViewHost from 309 // which the current drag originated. These are used to ensure that drag 310 // events do not fire over a cross-site frame (with respect to the source 311 // frame) in the same page (see crbug.com/666858). Specifically, the 312 // RenderViewHost is used to check the "same page" property, while the 313 // RenderProcessHost is used to check the "cross-site" property. Note that the 314 // reason the RenderProcessHost is tracked instead of the RenderWidgetHost is 315 // so that we still allow drags between non-contiguous same-site frames (such 316 // frames will have the same process, but different widgets). Note also that 317 // the RenderViewHost may not be in the same process as the RenderProcessHost, 318 // since the view corresponds to the page, while the process is specific to 319 // the frame from which the drag started. 320 int drag_start_process_id_; 321 GlobalRoutingID drag_start_view_id_; 322 323 // Responsible for handling gesture-nav and pull-to-refresh UI. 324 std::unique_ptr<GestureNavSimple> gesture_nav_simple_; 325 326 // This is true when the drag is in process from the perspective of this 327 // class. It means it gets true when drag enters and gets reset when either 328 // drop happens or drag exits. 329 bool drag_in_progress_; 330 331 bool init_rwhv_with_null_parent_for_testing_; 332 333 base::WeakPtrFactory<WebContentsViewAura> weak_ptr_factory_{this}; 334 335 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura); 336 }; 337 338 } // namespace content 339 340 #endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_AURA_H_ 341