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 CHROME_BROWSER_SESSIONS_BASE_SESSION_SERVICE_H_ 6 #define CHROME_BROWSER_SESSIONS_BASE_SESSION_SERVICE_H_ 7 8 #include "base/basictypes.h" 9 #include "base/callback.h" 10 #include "base/files/file_path.h" 11 #include "base/gtest_prod_util.h" 12 #include "base/location.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/scoped_vector.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/threading/sequenced_worker_pool.h" 17 #include "chrome/browser/common/cancelable_request.h" 18 #include "chrome/browser/sessions/session_id.h" 19 #include "chrome/common/cancelable_task_tracker.h" 20 #include "url/gurl.h" 21 22 class Profile; 23 class SessionBackend; 24 class SessionCommand; 25 26 namespace sessions { 27 class SerializedNavigationEntry; 28 } 29 30 // BaseSessionService is the super class of both tab restore service and 31 // session service. It contains commonality needed by both, in particular 32 // it manages a set of SessionCommands that are periodically sent to a 33 // SessionBackend. 34 class BaseSessionService : public CancelableRequestProvider { 35 public: 36 // Identifies the type of session service this is. This is used by the 37 // backend to determine the name of the files. 38 enum SessionType { 39 SESSION_RESTORE, 40 TAB_RESTORE 41 }; 42 43 // Creates a new BaseSessionService. After creation you need to invoke 44 // Init. 45 // |type| gives the type of session service, |profile| the profile and 46 // |path| the path to save files to. If |profile| is non-NULL, |path| is 47 // ignored and instead the path comes from the profile. 48 BaseSessionService(SessionType type, 49 Profile* profile, 50 const base::FilePath& path); 51 52 Profile* profile() const { return profile_; } 53 54 // Deletes the last session. 55 void DeleteLastSession(); 56 57 typedef base::Callback<void(ScopedVector<SessionCommand>)> 58 InternalGetCommandsCallback; 59 60 protected: 61 virtual ~BaseSessionService(); 62 63 // Returns the backend. 64 SessionBackend* backend() const { return backend_.get(); } 65 66 // Returns the set of commands that needed to be scheduled. The commands 67 // in the vector are owned by BaseSessionService, until they are scheduled 68 // on the backend at which point the backend owns the commands. 69 std::vector<SessionCommand*>& pending_commands() { 70 return pending_commands_; 71 } 72 73 // Whether the next save resets the file before writing to it. 74 void set_pending_reset(bool value) { pending_reset_ = value; } 75 bool pending_reset() const { return pending_reset_; } 76 77 // Returns the number of commands sent down since the last reset. 78 int commands_since_reset() const { return commands_since_reset_; } 79 80 // Schedules a command. This adds |command| to pending_commands_ and 81 // invokes StartSaveTimer to start a timer that invokes Save at a later 82 // time. 83 virtual void ScheduleCommand(SessionCommand* command); 84 85 // Starts the timer that invokes Save (if timer isn't already running). 86 void StartSaveTimer(); 87 88 // Saves pending commands to the backend. This is invoked from the timer 89 // scheduled by StartSaveTimer. 90 virtual void Save(); 91 92 // Creates a SessionCommand that represents a navigation. 93 SessionCommand* CreateUpdateTabNavigationCommand( 94 SessionID::id_type command_id, 95 SessionID::id_type tab_id, 96 const sessions::SerializedNavigationEntry& navigation); 97 98 // Creates a SessionCommand that represents marking a tab as an application. 99 SessionCommand* CreateSetTabExtensionAppIDCommand( 100 SessionID::id_type command_id, 101 SessionID::id_type tab_id, 102 const std::string& extension_id); 103 104 // Creates a SessionCommand that containing user agent override used by a 105 // tab's navigations. 106 SessionCommand* CreateSetTabUserAgentOverrideCommand( 107 SessionID::id_type command_id, 108 SessionID::id_type tab_id, 109 const std::string& user_agent_override); 110 111 // Creates a SessionCommand stores a browser window's app name. 112 SessionCommand* CreateSetWindowAppNameCommand( 113 SessionID::id_type command_id, 114 SessionID::id_type window_id, 115 const std::string& app_name); 116 117 // Converts a SessionCommand previously created by 118 // CreateUpdateTabNavigationCommand into a 119 // sessions::SerializedNavigationEntry. Returns true on success. If 120 // successful |tab_id| is set to the id of the restored tab. 121 bool RestoreUpdateTabNavigationCommand( 122 const SessionCommand& command, 123 sessions::SerializedNavigationEntry* navigation, 124 SessionID::id_type* tab_id); 125 126 // Extracts a SessionCommand as previously created by 127 // CreateSetTabExtensionAppIDCommand into the tab id and application 128 // extension id. 129 bool RestoreSetTabExtensionAppIDCommand( 130 const SessionCommand& command, 131 SessionID::id_type* tab_id, 132 std::string* extension_app_id); 133 134 // Extracts a SessionCommand as previously created by 135 // CreateSetTabUserAgentOverrideCommand into the tab id and user agent. 136 bool RestoreSetTabUserAgentOverrideCommand( 137 const SessionCommand& command, 138 SessionID::id_type* tab_id, 139 std::string* user_agent_override); 140 141 // Extracts a SessionCommand as previously created by 142 // CreateSetWindowAppNameCommand into the window id and application name. 143 bool RestoreSetWindowAppNameCommand( 144 const SessionCommand& command, 145 SessionID::id_type* window_id, 146 std::string* app_name); 147 148 // Returns true if the entry at specified |url| should be written to disk. 149 bool ShouldTrackEntry(const GURL& url); 150 151 // Invokes SessionBackend::ReadLastSessionCommands with callback on the 152 // backend thread. 153 // If testing, SessionBackend::ReadLastSessionCommands is invoked directly. 154 CancelableTaskTracker::TaskId ScheduleGetLastSessionCommands( 155 const InternalGetCommandsCallback& callback, 156 CancelableTaskTracker* tracker); 157 158 // This posts the task to the SequencedWorkerPool, or run immediately 159 // if the SequencedWorkerPool has been shutdown. 160 bool RunTaskOnBackendThread(const tracked_objects::Location& from_here, 161 const base::Closure& task); 162 163 // Max number of navigation entries in each direction we'll persist. 164 static const int max_persist_navigation_count; 165 166 private: 167 friend class BetterSessionRestoreCrashTest; 168 169 // The profile. This may be null during testing. 170 Profile* profile_; 171 172 // The backend. 173 scoped_refptr<SessionBackend> backend_; 174 175 // Used to invoke Save. 176 base::WeakPtrFactory<BaseSessionService> weak_factory_; 177 178 // Commands we need to send over to the backend. 179 std::vector<SessionCommand*> pending_commands_; 180 181 // Whether the backend file should be recreated the next time we send 182 // over the commands. 183 bool pending_reset_; 184 185 // The number of commands sent to the backend before doing a reset. 186 int commands_since_reset_; 187 188 // A token to make sure that all tasks will be serialized. 189 base::SequencedWorkerPool::SequenceToken sequence_token_; 190 191 DISALLOW_COPY_AND_ASSIGN(BaseSessionService); 192 }; 193 194 #endif // CHROME_BROWSER_SESSIONS_BASE_SESSION_SERVICE_H_ 195