1 // Copyright 2020 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 WEBLAYER_BROWSER_PERSISTENCE_BROWSER_PERSISTER_H_
6 #define WEBLAYER_BROWSER_PERSISTENCE_BROWSER_PERSISTER_H_
7 
8 #include <stddef.h>
9 
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <utility>
14 #include <vector>
15 
16 #include "base/macros.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/scoped_observer.h"
19 #include "components/sessions/content/session_tab_helper_delegate.h"
20 #include "components/sessions/core/command_storage_manager_delegate.h"
21 #include "components/sessions/core/session_service_commands.h"
22 #include "weblayer/browser/tab_impl.h"
23 #include "weblayer/public/browser_observer.h"
24 
25 class SessionID;
26 
27 namespace sessions {
28 class SessionCommand;
29 }
30 
31 namespace weblayer {
32 
33 class BrowserImpl;
34 
35 // BrowserPersister is responsible for maintaining the state of tabs in a
36 // single Browser so that they can be restored at a later date. The state is
37 // written to a file. To avoid having to write the complete state anytime
38 // something changes interesting events (represented as SessionCommands) are
39 // written to disk. To restore, the events are read back and the state
40 // recreated. At certain times the file is truncated and rebuilt from the
41 // current state.
42 class BrowserPersister : public sessions::CommandStorageManagerDelegate,
43                          public sessions::SessionTabHelperDelegate,
44                          public BrowserObserver,
45                          public TabImpl::DataObserver {
46  public:
47   BrowserPersister(const base::FilePath& path,
48                    BrowserImpl* browser,
49                    const std::vector<uint8_t>& decryption_key);
50 
51   BrowserPersister(const BrowserPersister&) = delete;
52   BrowserPersister& operator=(const BrowserPersister&) = delete;
53 
54   ~BrowserPersister() override;
55 
is_restore_in_progress()56   bool is_restore_in_progress() const { return is_restore_in_progress_; }
57 
58   void SaveIfNecessary();
59 
60   // Returns the key used to encrypt the file. Empty if not encrypted.
61   // Encryption is done when saving and the profile is off the record.
62   const std::vector<uint8_t>& GetCryptoKey() const;
63 
64  private:
65   friend class BrowserPersisterTestHelper;
66 
67   using IdToRange = std::map<SessionID, std::pair<int, int>>;
68 
69   // CommandStorageManagerDelegate:
70   bool ShouldUseDelayedSave() override;
71   void OnWillSaveCommands() override;
72   void OnGeneratedNewCryptoKey(const std::vector<uint8_t>& key) override;
73 
74   // BrowserObserver;
75   void OnTabAdded(Tab* tab) override;
76   void OnTabRemoved(Tab* tab, bool active_tab_changed) override;
77   void OnActiveTabChanged(Tab* tab) override;
78 
79   // TabImpl::DataObserver:
80   void OnDataChanged(TabImpl* tab,
81                      const std::map<std::string, std::string>& data) override;
82 
83   // sessions::SessionTabHelperDelegate:
84   void SetTabUserAgentOverride(const SessionID& window_id,
85                                const SessionID& tab_id,
86                                const sessions::SerializedUserAgentOverride&
87                                    user_agent_override) override;
88   void SetSelectedNavigationIndex(const SessionID& window_id,
89                                   const SessionID& tab_id,
90                                   int index) override;
91   void UpdateTabNavigation(
92       const SessionID& window_id,
93       const SessionID& tab_id,
94       const sessions::SerializedNavigationEntry& navigation) override;
95   void TabNavigationPathPruned(const SessionID& window_id,
96                                const SessionID& tab_id,
97                                int index,
98                                int count) override;
99   void TabNavigationPathEntriesDeleted(const SessionID& window_id,
100                                        const SessionID& tab_id) override;
101 
102   // Schedules recreating the file on the next save.
103   void ScheduleRebuildOnNextSave();
104 
105   // Called with the contents of the previous session.
106   void OnGotCurrentSessionCommands(
107       std::vector<std::unique_ptr<sessions::SessionCommand>> commands);
108 
109   // Schedules commands to recreate the state of the specified tab.
110   void BuildCommandsForTab(TabImpl* tab, int index_in_window);
111 
112   // Schedules commands to recreate the state of |browser_|.
113   void BuildCommandsForBrowser();
114 
115   // Schedules the specified command.
116   void ScheduleCommand(std::unique_ptr<sessions::SessionCommand> command);
117 
118   void ProcessRestoreCommands(
119       const std::vector<std::unique_ptr<sessions::SessionWindow>>& windows);
120 
121   BrowserImpl* browser_;
122 
123   // ID used for the browser. The sessions code requires each tab to be
124   // associated with a browser.
125   const SessionID browser_session_id_;
126 
127   std::unique_ptr<sessions::CommandStorageManager> command_storage_manager_;
128 
129   // Maps from session tab id to the range of navigation entries that has
130   // been written to disk.
131   IdToRange tab_to_available_range_;
132 
133   // Force session commands to be rebuild before next save event.
134   bool rebuild_on_next_save_;
135 
136   std::vector<uint8_t> crypto_key_;
137 
138   ScopedObserver<TabImpl,
139                  TabImpl::DataObserver,
140                  &TabImpl::AddDataObserver,
141                  &TabImpl::RemoveDataObserver>
142       data_observer_{this};
143 
144   // True while asynchronously reading the state to restore.
145   bool is_restore_in_progress_ = true;
146 
147   base::WeakPtrFactory<BrowserPersister> weak_factory_{this};
148 };
149 
150 }  // namespace weblayer
151 
152 #endif  // WEBLAYER_BROWSER_PERSISTENCE_BROWSER_PERSISTER_H_
153