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