Web Replay: capture and replay mouse events
[WebKit-https.git] / Source / WebCore / replay / ReplayController.h
1 /*
2  * Copyright (C) 2011-2013 University of Washington. All rights reserved.
3  * Copyright (C) 2014 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifndef ReplayController_h
29 #define ReplayController_h
30
31 #if ENABLE(WEB_REPLAY)
32
33 #include "EventLoopInputDispatcher.h"
34 #include <wtf/Noncopyable.h>
35 #include <wtf/Vector.h>
36
37 namespace JSC {
38 class InputCursor;
39 }
40
41 namespace WebCore {
42
43 class DOMWindow;
44 class Document;
45 class DocumentLoader;
46 class Element;
47 class Event;
48 class EventLoopInputBase;
49 class Frame;
50 class Node;
51 class Page;
52 class ReplaySession;
53 class ReplaySessionSegment;
54
55 // Each state may transition to the state immediately above or below it.
56 // SessionState transitions are only allowed when SegmentState is Unloaded.
57 enum class SessionState {
58     Capturing,
59     // Neither capturing or replaying. m_currentPosition is not valid in this state.
60     Inactive,
61     Replaying,
62 };
63
64 // Each state may transition to the state immediately above or below it.
65 enum class SegmentState {
66     // Inputs can be appended into an unassociated session segment.
67     // We can stop capturing, which reverts to the Unloaded state.
68     Appending,
69     // No session segment is loaded.
70     // We can start capturing, or load a segment (and then replay it).
71     Unloaded,
72     // A session segment is loaded.
73     // We can unload the segment, or begin playback from m_currentPosition.
74     Loaded,
75     // The controller is actively dispatching event loop inputs.
76     // We can pause or cancel playback, which reverts to the Loaded state.
77     Dispatching,
78 };
79
80 struct ReplayPosition {
81     ReplayPosition(unsigned segmentOffset, unsigned inputOffset)
82         : segmentOffset(segmentOffset)
83         , inputOffset(inputOffset)
84     {
85     }
86
87     // By convention, this position represents the end of the last segment of the session.
88     ReplayPosition()
89         : segmentOffset(0)
90         , inputOffset(0)
91     {
92     }
93
94     bool operator<(const ReplayPosition& other)
95     {
96         return segmentOffset <= other.segmentOffset && inputOffset < other.inputOffset;
97     }
98
99     bool operator==(const ReplayPosition& other)
100     {
101         return segmentOffset == other.segmentOffset && inputOffset == other.inputOffset;
102     }
103
104     unsigned segmentOffset;
105     unsigned inputOffset;
106 };
107
108 class ReplayController final : public EventLoopInputDispatcherClient {
109     WTF_MAKE_NONCOPYABLE(ReplayController);
110 public:
111     ReplayController(Page&);
112
113     void startCapturing();
114     void stopCapturing();
115
116     // Start or resume playback with default speed and target replay position.
117     void startPlayback();
118     void pausePlayback();
119     void cancelPlayback();
120
121     void replayToPosition(const ReplayPosition&, DispatchSpeed = DispatchSpeed::FastForward);
122     void replayToCompletion(DispatchSpeed speed = DispatchSpeed::FastForward)
123     {
124         replayToPosition(ReplayPosition(), speed);
125     }
126
127     void switchSession(PassRefPtr<ReplaySession>);
128
129     // InspectorReplayAgent notifications.
130     void frameNavigated(DocumentLoader*);
131     void frameDetached(Frame*);
132
133     Page& page() const { return m_page; }
134     SessionState sessionState() const { return m_sessionState; }
135     PassRefPtr<ReplaySession> loadedSession() const;
136     PassRefPtr<ReplaySessionSegment> loadedSegment() const;
137     JSC::InputCursor& activeInputCursor() const;
138
139 private:
140     // EventLoopInputDispatcherClient API
141     virtual void willDispatchInput(const EventLoopInputBase&) override;
142     virtual void didDispatchInput(const EventLoopInputBase&) override;
143     virtual void didDispatchFinalInput() override;
144
145     void createSegment();
146     void completeSegment();
147
148     void loadSegmentAtIndex(size_t);
149     void unloadSegment(bool suppressNotifications = false);
150
151     EventLoopInputDispatcher& dispatcher() const;
152
153     void setSessionState(SessionState);
154
155     Page& m_page;
156
157     RefPtr<ReplaySessionSegment> m_loadedSegment;
158     RefPtr<ReplaySession> m_loadedSession;
159     const RefPtr<JSC::InputCursor> m_emptyCursor;
160     // The active cursor is set to nullptr when invalid.
161     RefPtr<JSC::InputCursor> m_activeCursor;
162
163     // This position is valid when SessionState == Replaying.
164     ReplayPosition m_targetPosition;
165     // This position is valid when SessionState != Inactive.
166     ReplayPosition m_currentPosition;
167     SegmentState m_segmentState;
168     // This tracks state across multiple segments. When navigating the main frame,
169     // there is a small interval during segment switching when no segment is loaded.
170     SessionState m_sessionState;
171
172     DispatchSpeed m_dispatchSpeed;
173 };
174
175 } // namespace WebCore
176
177 #endif // ENABLE(WEB_REPLAY)
178
179 #endif // ReplayController_h