1 // Copyright (c) 2015 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 CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_
6 #define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_
7 
8 #include <utility>
9 
10 #include "base/callback.h"
11 #include "base/macros.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_hide_callback.h"
15 #include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h"
16 #include "components/content_settings/core/common/content_settings.h"
17 
18 // This class implements mouselock behavior.
19 class MouseLockController : public ExclusiveAccessControllerBase {
20  public:
21   explicit MouseLockController(ExclusiveAccessManager* manager);
22   ~MouseLockController() override;
23 
24   // Returns true if the mouse is locked.
25   bool IsMouseLocked() const;
26 
27   // Returns true if the mouse was locked and no notification should be
28   // displayed to the user. This is the case when a notice has already been
29   // displayed to the user, and the application voluntarily unlocks, then
30   // re-locks the mouse (a duplicate notification should not be given). See
31   // content::MouseLockDispatcher::LockMouse.
32   bool IsMouseLockedSilently() const;
33 
34   void RequestToLockMouse(content::WebContents* web_contents,
35                           bool user_gesture,
36                           bool last_unlocked_by_target);
37 
38   // Override from ExclusiveAccessControllerBase
39   bool HandleUserPressedEscape() override;
40 
41   void ExitExclusiveAccessToPreviousState() override;
42 
43   // Called by Browser::LostMouseLock.
44   void LostMouseLock();
45 
46   void UnlockMouse();
47 
set_lock_state_callback_for_test(base::OnceClosure callback)48   void set_lock_state_callback_for_test(base::OnceClosure callback) {
49     lock_state_callback_for_test_ = std::move(callback);
50   }
51 
52  private:
53   friend class ExclusiveAccessTest;
54 
55   enum MouseLockState {
56     MOUSELOCK_UNLOCKED,
57     // Mouse has been locked.
58     MOUSELOCK_LOCKED,
59     // Mouse has been locked silently, with no notification to user.
60     MOUSELOCK_LOCKED_SILENTLY
61   };
62 
63   void ExitExclusiveAccessIfNecessary() override;
64   void NotifyTabExclusiveAccessLost() override;
65   void RecordBubbleReshowsHistogram(int bubble_reshow_count) override;
66 
67   void OnBubbleHidden(content::WebContents*, ExclusiveAccessBubbleHideReason);
68 
69   MouseLockState mouse_lock_state_;
70 
71   // Optionally a WebContents instance that is granted permission to silently
72   // lock the mouse. This is granted only if the WebContents instance has
73   // previously locked and displayed the permission bubble until the bubble
74   // time out has expired. https://crbug.com/725370
75   content::WebContents* web_contents_granted_silent_mouse_lock_permission_ =
76       nullptr;
77 
78   // If true, does not call into the WebContents to lock the mouse. Just assumes
79   // that it works. This may be necessary when calling
80   // Browser::RequestToLockMouse in tests, because the proper signal will not
81   // have been passed to the RenderViewHost.
82   bool fake_mouse_lock_for_test_;
83 
84   // If set, |bubble_hide_callback_for_test_| will be called during
85   // |OnBubbleHidden()|.
86   ExclusiveAccessBubbleHideCallbackForTest bubble_hide_callback_for_test_;
87 
88   // Called when the page requests (successfully or not) or loses mouse lock.
89   base::OnceClosure lock_state_callback_for_test_;
90 
91   // Timestamp when the user last successfully escaped from a lock request.
92   base::TimeTicks last_user_escape_time_;
93 
94   base::WeakPtrFactory<MouseLockController> weak_ptr_factory_{this};
95 
96   DISALLOW_COPY_AND_ASSIGN(MouseLockController);
97 };
98 
99 #endif  //  CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_
100