1 // Copyright 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 COMPONENTS_SESSIONS_CORE_COMMAND_STORAGE_MANAGER_H_
6 #define COMPONENTS_SESSIONS_CORE_COMMAND_STORAGE_MANAGER_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <vector>
12 
13 #include "base/callback.h"
14 #include "base/files/file_path.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/weak_ptr.h"
17 #include "components/sessions/core/sessions_export.h"
18 
19 namespace base {
20 class SequencedTaskRunner;
21 }
22 
23 namespace sessions {
24 class CommandStorageManagerDelegate;
25 class SessionCommand;
26 class CommandStorageBackend;
27 
28 // CommandStorageManager is responsible for reading/writing SessionCommands
29 // to disk. SessionCommands are used to save and restore the state of the
30 // browser. CommandStorageManager runs on the main thread and uses
31 // CommandStorageBackend (which runs on a background task runner) for the actual
32 // reading/writing. In hopes of minimizing IO, SessionCommands are queued up
33 // and processed after a delay.
34 class SESSIONS_EXPORT CommandStorageManager {
35  public:
36   using GetCommandsCallback =
37       base::OnceCallback<void(std::vector<std::unique_ptr<SessionCommand>>)>;
38 
39   // Creates a new CommandStorageManager. After creation you need to invoke
40   // Init. |delegate| will remain owned by the creator and it is guaranteed
41   // that its lifetime surpasses this class. |path| is the path to save files
42   // to. If |enable_crypto| is true, the contents of the file are encrypted.
43   CommandStorageManager(const base::FilePath& path,
44                         CommandStorageManagerDelegate* delegate,
45                         bool enable_crypto = false);
46   CommandStorageManager(const CommandStorageManager&) = delete;
47   CommandStorageManager& operator=(const CommandStorageManager&) = delete;
48   virtual ~CommandStorageManager();
49 
50   // Helper to generate a new key.
51   static std::vector<uint8_t> CreateCryptoKey();
52 
53   // Returns the set of commands which were scheduled to be written. Once
54   // committed to the backend, the commands are removed from here.
pending_commands()55   const std::vector<std::unique_ptr<SessionCommand>>& pending_commands() {
56     return pending_commands_;
57   }
58 
59   // Whether the next save resets the file before writing to it.
set_pending_reset(bool value)60   void set_pending_reset(bool value) { pending_reset_ = value; }
pending_reset()61   bool pending_reset() const { return pending_reset_; }
62 
63   // Returns the number of commands sent down since the last reset.
commands_since_reset()64   int commands_since_reset() const { return commands_since_reset_; }
65 
66   // Schedules a command. This adds |command| to pending_commands_ and
67   // invokes StartSaveTimer to start a timer that invokes Save at a later
68   // time.
69   void ScheduleCommand(std::unique_ptr<SessionCommand> command);
70 
71   // Appends a command as part of a general rebuild. This will neither count
72   // against a rebuild, nor will it trigger a save of commands.
73   void AppendRebuildCommand(std::unique_ptr<SessionCommand> command);
74   void AppendRebuildCommands(
75       std::vector<std::unique_ptr<SessionCommand>> commands);
76 
77   // Erase the |old_command| from the list of commands.
78   // The passed command will automatically be deleted.
79   void EraseCommand(SessionCommand* old_command);
80 
81   // Swap a |new_command| into the list of queued commands at the location of
82   // the |old_command|. The |old_command| will be automatically deleted in the
83   // process.
84   void SwapCommand(SessionCommand* old_command,
85                    std::unique_ptr<SessionCommand> new_command);
86 
87   // Clears all commands from the list.
88   void ClearPendingCommands();
89 
90   // Starts the timer that invokes Save (if timer isn't already running).
91   void StartSaveTimer();
92 
93   // Passes all pending commands to the backend for saving.
94   void Save();
95 
96   // Returns true if StartSaveTimer() has been called, but a save has not yet
97   // occurred.
98   bool HasPendingSave() const;
99 
100   // Requests the commands for the current session. If |decryption_key| is
101   // non-empty it is used to decrypt the contents of the file.
102   // WARNING: |callback| may be called after |this| is deleted. In other words,
103   // be sure to use a WeakPtr with |callback|.
104   void GetCurrentSessionCommands(GetCommandsCallback callback,
105                                  const std::vector<uint8_t>& decryption_key);
106 
107  protected:
108   // Provided for subclasses.
109   CommandStorageManager(scoped_refptr<CommandStorageBackend> backend,
110                         CommandStorageManagerDelegate* delegate);
111 
112   // Creates a SequencedTaskRunner suitable for the backend.
113   static scoped_refptr<base::SequencedTaskRunner>
114   CreateDefaultBackendTaskRunner();
115 
backend_task_runner()116   scoped_refptr<base::SequencedTaskRunner> backend_task_runner() {
117     return backend_task_runner_;
118   }
119 
backend()120   CommandStorageBackend* backend() { return backend_.get(); }
121 
122  private:
123   friend class CommandStorageManagerTestHelper;
124 
125   // The backend object which reads and saves commands.
126   scoped_refptr<CommandStorageBackend> backend_;
127 
128   // If true, all commands are encrypted.
129   bool use_crypto_ = false;
130 
131   // Commands we need to send over to the backend.
132   std::vector<std::unique_ptr<SessionCommand>> pending_commands_;
133 
134   // Whether the backend file should be recreated the next time we send
135   // over the commands.
136   bool pending_reset_ = false;
137 
138   // The number of commands sent to the backend before doing a reset.
139   int commands_since_reset_ = 0;
140 
141   CommandStorageManagerDelegate* delegate_;
142 
143   // TaskRunner all backend tasks are run on. This is a SequencedTaskRunner as
144   // all tasks *must* be processed in the order they are scheduled.
145   scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
146 
147   // Used solely for saving after a delay, and not to be used for any other
148   // purposes.
149   base::WeakPtrFactory<CommandStorageManager> weak_factory_for_timer_{this};
150 };
151 
152 }  // namespace sessions
153 
154 #endif  // COMPONENTS_SESSIONS_CORE_COMMAND_STORAGE_MANAGER_H_
155