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