| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/sessions/core/session_backend.h" | 5 #include "components/sessions/core/session_backend.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/files/file.h" | 11 #include "base/files/file.h" |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/scoped_vector.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/threading/thread_restrictions.h" | 16 #include "base/threading/thread_restrictions.h" |
| 17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 18 | 18 |
| 19 using base::TimeTicks; | 19 using base::TimeTicks; |
| 20 | 20 |
| 21 namespace sessions { | 21 namespace sessions { |
| 22 | 22 |
| 23 // File version number. | 23 // File version number. |
| 24 static const int32_t kFileCurrentVersion = 1; | 24 static const int32_t kFileCurrentVersion = 1; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 48 | 48 |
| 49 explicit SessionFileReader(const base::FilePath& path) | 49 explicit SessionFileReader(const base::FilePath& path) |
| 50 : errored_(false), | 50 : errored_(false), |
| 51 buffer_(SessionBackend::kFileReadBufferSize, 0), | 51 buffer_(SessionBackend::kFileReadBufferSize, 0), |
| 52 buffer_position_(0), | 52 buffer_position_(0), |
| 53 available_count_(0) { | 53 available_count_(0) { |
| 54 file_.reset(new base::File( | 54 file_.reset(new base::File( |
| 55 path, base::File::FLAG_OPEN | base::File::FLAG_READ)); | 55 path, base::File::FLAG_OPEN | base::File::FLAG_READ)); |
| 56 } | 56 } |
| 57 // Reads the contents of the file specified in the constructor, returning | 57 // Reads the contents of the file specified in the constructor, returning |
| 58 // true on success. It is up to the caller to free all SessionCommands | 58 // true on success, and filling up |commands| with commands. |
| 59 // added to commands. | |
| 60 bool Read(sessions::BaseSessionService::SessionType type, | 59 bool Read(sessions::BaseSessionService::SessionType type, |
| 61 ScopedVector<sessions::SessionCommand>* commands); | 60 std::vector<std::unique_ptr<sessions::SessionCommand>>* commands); |
| 62 | 61 |
| 63 private: | 62 private: |
| 64 // Reads a single command, returning it. A return value of NULL indicates | 63 // Reads a single command, returning it. A return value of NULL indicates |
| 65 // either there are no commands, or there was an error. Use errored_ to | 64 // either there are no commands, or there was an error. Use errored_ to |
| 66 // distinguish the two. If NULL is returned, and there is no error, it means | 65 // distinguish the two. If NULL is returned, and there is no error, it means |
| 67 // the end of file was successfully reached. | 66 // the end of file was successfully reached. |
| 68 sessions::SessionCommand* ReadCommand(); | 67 std::unique_ptr<sessions::SessionCommand> ReadCommand(); |
| 69 | 68 |
| 70 // Shifts the unused portion of buffer_ to the beginning and fills the | 69 // Shifts the unused portion of buffer_ to the beginning and fills the |
| 71 // remaining portion with data from the file. Returns false if the buffer | 70 // remaining portion with data from the file. Returns false if the buffer |
| 72 // couldn't be filled. A return value of false only signals an error if | 71 // couldn't be filled. A return value of false only signals an error if |
| 73 // errored_ is set to true. | 72 // errored_ is set to true. |
| 74 bool FillBuffer(); | 73 bool FillBuffer(); |
| 75 | 74 |
| 76 // Whether an error condition has been detected ( | 75 // Whether an error condition has been detected ( |
| 77 bool errored_; | 76 bool errored_; |
| 78 | 77 |
| 79 // As we read from the file, data goes here. | 78 // As we read from the file, data goes here. |
| 80 std::string buffer_; | 79 std::string buffer_; |
| 81 | 80 |
| 82 // The file. | 81 // The file. |
| 83 std::unique_ptr<base::File> file_; | 82 std::unique_ptr<base::File> file_; |
| 84 | 83 |
| 85 // Position in buffer_ of the data. | 84 // Position in buffer_ of the data. |
| 86 size_t buffer_position_; | 85 size_t buffer_position_; |
| 87 | 86 |
| 88 // Number of available bytes; relative to buffer_position_. | 87 // Number of available bytes; relative to buffer_position_. |
| 89 size_t available_count_; | 88 size_t available_count_; |
| 90 | 89 |
| 91 DISALLOW_COPY_AND_ASSIGN(SessionFileReader); | 90 DISALLOW_COPY_AND_ASSIGN(SessionFileReader); |
| 92 }; | 91 }; |
| 93 | 92 |
| 94 bool SessionFileReader::Read(sessions::BaseSessionService::SessionType type, | 93 bool SessionFileReader::Read( |
| 95 ScopedVector<sessions::SessionCommand>* commands) { | 94 sessions::BaseSessionService::SessionType type, |
| 95 std::vector<std::unique_ptr<sessions::SessionCommand>>* commands) { |
| 96 if (!file_->IsValid()) | 96 if (!file_->IsValid()) |
| 97 return false; | 97 return false; |
| 98 FileHeader header; | 98 FileHeader header; |
| 99 int read_count; | 99 int read_count; |
| 100 TimeTicks start_time = TimeTicks::Now(); | 100 TimeTicks start_time = TimeTicks::Now(); |
| 101 read_count = file_->ReadAtCurrentPos(reinterpret_cast<char*>(&header), | 101 read_count = file_->ReadAtCurrentPos(reinterpret_cast<char*>(&header), |
| 102 sizeof(header)); | 102 sizeof(header)); |
| 103 if (read_count != sizeof(header) || header.signature != kFileSignature || | 103 if (read_count != sizeof(header) || header.signature != kFileSignature || |
| 104 header.version != kFileCurrentVersion) | 104 header.version != kFileCurrentVersion) |
| 105 return false; | 105 return false; |
| 106 | 106 |
| 107 ScopedVector<sessions::SessionCommand> read_commands; | 107 std::vector<std::unique_ptr<sessions::SessionCommand>> read_commands; |
| 108 for (sessions::SessionCommand* command = ReadCommand(); command && !errored_; | 108 for (std::unique_ptr<sessions::SessionCommand> command = ReadCommand(); |
| 109 command = ReadCommand()) | 109 command && !errored_; command = ReadCommand()) |
| 110 read_commands.push_back(command); | 110 read_commands.push_back(std::move(command)); |
| 111 if (!errored_) | 111 if (!errored_) |
| 112 read_commands.swap(*commands); | 112 read_commands.swap(*commands); |
| 113 if (type == sessions::BaseSessionService::TAB_RESTORE) { | 113 if (type == sessions::BaseSessionService::TAB_RESTORE) { |
| 114 UMA_HISTOGRAM_TIMES("TabRestore.read_session_file_time", | 114 UMA_HISTOGRAM_TIMES("TabRestore.read_session_file_time", |
| 115 TimeTicks::Now() - start_time); | 115 TimeTicks::Now() - start_time); |
| 116 } else { | 116 } else { |
| 117 UMA_HISTOGRAM_TIMES("SessionRestore.read_session_file_time", | 117 UMA_HISTOGRAM_TIMES("SessionRestore.read_session_file_time", |
| 118 TimeTicks::Now() - start_time); | 118 TimeTicks::Now() - start_time); |
| 119 } | 119 } |
| 120 return !errored_; | 120 return !errored_; |
| 121 } | 121 } |
| 122 | 122 |
| 123 sessions::SessionCommand* SessionFileReader::ReadCommand() { | 123 std::unique_ptr<sessions::SessionCommand> SessionFileReader::ReadCommand() { |
| 124 // Make sure there is enough in the buffer for the size of the next command. | 124 // Make sure there is enough in the buffer for the size of the next command. |
| 125 if (available_count_ < sizeof(size_type)) { | 125 if (available_count_ < sizeof(size_type)) { |
| 126 if (!FillBuffer()) | 126 if (!FillBuffer()) |
| 127 return NULL; | 127 return NULL; |
| 128 if (available_count_ < sizeof(size_type)) { | 128 if (available_count_ < sizeof(size_type)) { |
| 129 VLOG(1) << "SessionFileReader::ReadCommand, file incomplete"; | 129 VLOG(1) << "SessionFileReader::ReadCommand, file incomplete"; |
| 130 // Still couldn't read a valid size for the command, assume write was | 130 // Still couldn't read a valid size for the command, assume write was |
| 131 // incomplete and return NULL. | 131 // incomplete and return NULL. |
| 132 return NULL; | 132 return NULL; |
| 133 } | 133 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 150 buffer_.resize((command_size / 1024 + 1) * 1024, 0); | 150 buffer_.resize((command_size / 1024 + 1) * 1024, 0); |
| 151 if (!FillBuffer() || command_size > available_count_) { | 151 if (!FillBuffer() || command_size > available_count_) { |
| 152 // Again, assume the file was ok, and just the last chunk was lost. | 152 // Again, assume the file was ok, and just the last chunk was lost. |
| 153 VLOG(1) << "SessionFileReader::ReadCommand, last chunk lost"; | 153 VLOG(1) << "SessionFileReader::ReadCommand, last chunk lost"; |
| 154 return NULL; | 154 return NULL; |
| 155 } | 155 } |
| 156 } | 156 } |
| 157 const id_type command_id = buffer_[buffer_position_]; | 157 const id_type command_id = buffer_[buffer_position_]; |
| 158 // NOTE: command_size includes the size of the id, which is not part of | 158 // NOTE: command_size includes the size of the id, which is not part of |
| 159 // the contents of the SessionCommand. | 159 // the contents of the SessionCommand. |
| 160 sessions::SessionCommand* command = | 160 std::unique_ptr<sessions::SessionCommand> command = |
| 161 new sessions::SessionCommand(command_id, command_size - sizeof(id_type)); | 161 base::MakeUnique<sessions::SessionCommand>( |
| 162 command_id, command_size - sizeof(id_type)); |
| 162 if (command_size > sizeof(id_type)) { | 163 if (command_size > sizeof(id_type)) { |
| 163 memcpy(command->contents(), | 164 memcpy(command->contents(), |
| 164 &(buffer_[buffer_position_ + sizeof(id_type)]), | 165 &(buffer_[buffer_position_ + sizeof(id_type)]), |
| 165 command_size - sizeof(id_type)); | 166 command_size - sizeof(id_type)); |
| 166 } | 167 } |
| 167 buffer_position_ += command_size; | 168 buffer_position_ += command_size; |
| 168 available_count_ -= command_size; | 169 available_count_ -= command_size; |
| 169 return command; | 170 return command; |
| 170 } | 171 } |
| 171 | 172 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 | 221 |
| 221 inited_ = true; | 222 inited_ = true; |
| 222 | 223 |
| 223 // Create the directory for session info. | 224 // Create the directory for session info. |
| 224 base::CreateDirectory(path_to_dir_); | 225 base::CreateDirectory(path_to_dir_); |
| 225 | 226 |
| 226 MoveCurrentSessionToLastSession(); | 227 MoveCurrentSessionToLastSession(); |
| 227 } | 228 } |
| 228 | 229 |
| 229 void SessionBackend::AppendCommands( | 230 void SessionBackend::AppendCommands( |
| 230 ScopedVector<sessions::SessionCommand> commands, | 231 std::vector<std::unique_ptr<sessions::SessionCommand>> commands, |
| 231 bool reset_first) { | 232 bool reset_first) { |
| 232 Init(); | 233 Init(); |
| 233 // Make sure and check current_session_file_, if opening the file failed | 234 // Make sure and check current_session_file_, if opening the file failed |
| 234 // current_session_file_ will be NULL. | 235 // current_session_file_ will be NULL. |
| 235 if ((reset_first && !empty_file_) || !current_session_file_.get() || | 236 if ((reset_first && !empty_file_) || !current_session_file_.get() || |
| 236 !current_session_file_->IsValid()) { | 237 !current_session_file_->IsValid()) { |
| 237 ResetFile(); | 238 ResetFile(); |
| 238 } | 239 } |
| 239 // Need to check current_session_file_ again, ResetFile may fail. | 240 // Need to check current_session_file_ again, ResetFile may fail. |
| 240 if (current_session_file_.get() && current_session_file_->IsValid() && | 241 if (current_session_file_.get() && current_session_file_->IsValid() && |
| 241 !AppendCommandsToFile(current_session_file_.get(), commands)) { | 242 !AppendCommandsToFile(current_session_file_.get(), commands)) { |
| 242 current_session_file_.reset(NULL); | 243 current_session_file_.reset(NULL); |
| 243 } | 244 } |
| 244 empty_file_ = false; | 245 empty_file_ = false; |
| 245 } | 246 } |
| 246 | 247 |
| 247 void SessionBackend::ReadLastSessionCommands( | 248 void SessionBackend::ReadLastSessionCommands( |
| 248 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, | 249 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, |
| 249 const sessions::BaseSessionService::GetCommandsCallback& callback) { | 250 const sessions::BaseSessionService::GetCommandsCallback& callback) { |
| 250 if (is_canceled.Run()) | 251 if (is_canceled.Run()) |
| 251 return; | 252 return; |
| 252 | 253 |
| 253 Init(); | 254 Init(); |
| 254 | 255 |
| 255 ScopedVector<sessions::SessionCommand> commands; | 256 std::vector<std::unique_ptr<sessions::SessionCommand>> commands; |
| 256 ReadLastSessionCommandsImpl(&commands); | 257 ReadLastSessionCommandsImpl(&commands); |
| 257 callback.Run(std::move(commands)); | 258 callback.Run(std::move(commands)); |
| 258 } | 259 } |
| 259 | 260 |
| 260 bool SessionBackend::ReadLastSessionCommandsImpl( | 261 bool SessionBackend::ReadLastSessionCommandsImpl( |
| 261 ScopedVector<sessions::SessionCommand>* commands) { | 262 std::vector<std::unique_ptr<sessions::SessionCommand>>* commands) { |
| 262 Init(); | 263 Init(); |
| 263 SessionFileReader file_reader(GetLastSessionPath()); | 264 SessionFileReader file_reader(GetLastSessionPath()); |
| 264 return file_reader.Read(type_, commands); | 265 return file_reader.Read(type_, commands); |
| 265 } | 266 } |
| 266 | 267 |
| 267 void SessionBackend::DeleteLastSession() { | 268 void SessionBackend::DeleteLastSession() { |
| 268 Init(); | 269 Init(); |
| 269 base::DeleteFile(GetLastSessionPath(), false); | 270 base::DeleteFile(GetLastSessionPath(), false); |
| 270 } | 271 } |
| 271 | 272 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 292 } | 293 } |
| 293 | 294 |
| 294 if (base::PathExists(current_session_path)) | 295 if (base::PathExists(current_session_path)) |
| 295 base::DeleteFile(current_session_path, false); | 296 base::DeleteFile(current_session_path, false); |
| 296 | 297 |
| 297 // Create and open the file for the current session. | 298 // Create and open the file for the current session. |
| 298 ResetFile(); | 299 ResetFile(); |
| 299 } | 300 } |
| 300 | 301 |
| 301 bool SessionBackend::ReadCurrentSessionCommandsImpl( | 302 bool SessionBackend::ReadCurrentSessionCommandsImpl( |
| 302 ScopedVector<sessions::SessionCommand>* commands) { | 303 std::vector<std::unique_ptr<sessions::SessionCommand>>* commands) { |
| 303 Init(); | 304 Init(); |
| 304 SessionFileReader file_reader(GetCurrentSessionPath()); | 305 SessionFileReader file_reader(GetCurrentSessionPath()); |
| 305 return file_reader.Read(type_, commands); | 306 return file_reader.Read(type_, commands); |
| 306 } | 307 } |
| 307 | 308 |
| 308 bool SessionBackend::AppendCommandsToFile(base::File* file, | 309 bool SessionBackend::AppendCommandsToFile( |
| 309 const ScopedVector<sessions::SessionCommand>& commands) { | 310 base::File* file, |
| 310 for (ScopedVector<sessions::SessionCommand>::const_iterator i = | 311 const std::vector<std::unique_ptr<sessions::SessionCommand>>& commands) { |
| 311 commands.begin(); | 312 for (auto i = commands.begin(); i != commands.end(); ++i) { |
| 312 i != commands.end(); ++i) { | |
| 313 int wrote; | 313 int wrote; |
| 314 const size_type content_size = static_cast<size_type>((*i)->size()); | 314 const size_type content_size = static_cast<size_type>((*i)->size()); |
| 315 const size_type total_size = content_size + sizeof(id_type); | 315 const size_type total_size = content_size + sizeof(id_type); |
| 316 if (type_ == sessions::BaseSessionService::TAB_RESTORE) | 316 if (type_ == sessions::BaseSessionService::TAB_RESTORE) |
| 317 UMA_HISTOGRAM_COUNTS("TabRestore.command_size", total_size); | 317 UMA_HISTOGRAM_COUNTS("TabRestore.command_size", total_size); |
| 318 else | 318 else |
| 319 UMA_HISTOGRAM_COUNTS("SessionRestore.command_size", total_size); | 319 UMA_HISTOGRAM_COUNTS("SessionRestore.command_size", total_size); |
| 320 wrote = file->WriteAtCurrentPos(reinterpret_cast<const char*>(&total_size), | 320 wrote = file->WriteAtCurrentPos(reinterpret_cast<const char*>(&total_size), |
| 321 sizeof(total_size)); | 321 sizeof(total_size)); |
| 322 if (wrote != sizeof(total_size)) { | 322 if (wrote != sizeof(total_size)) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 base::FilePath SessionBackend::GetCurrentSessionPath() { | 402 base::FilePath SessionBackend::GetCurrentSessionPath() { |
| 403 base::FilePath path = path_to_dir_; | 403 base::FilePath path = path_to_dir_; |
| 404 if (type_ == sessions::BaseSessionService::TAB_RESTORE) | 404 if (type_ == sessions::BaseSessionService::TAB_RESTORE) |
| 405 path = path.AppendASCII(kCurrentTabSessionFileName); | 405 path = path.AppendASCII(kCurrentTabSessionFileName); |
| 406 else | 406 else |
| 407 path = path.AppendASCII(kCurrentSessionFileName); | 407 path = path.AppendASCII(kCurrentSessionFileName); |
| 408 return path; | 408 return path; |
| 409 } | 409 } |
| 410 | 410 |
| 411 } // namespace sessions | 411 } // namespace sessions |
| OLD | NEW |