| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/transport_security_persister.h" |
| |
| #include "base/file_path.h" |
| #include "base/file_util.h" |
| #include "base/message_loop.h" |
| #include "base/path_service.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "content/browser/browser_thread.h" |
| #include "net/base/transport_security_state.h" |
| |
| TransportSecurityPersister::TransportSecurityPersister(bool readonly) |
| : ALLOW_THIS_IN_INITIALIZER_LIST(save_coalescer_(this)), |
| readonly_(readonly) { |
| } |
| |
| TransportSecurityPersister::~TransportSecurityPersister() { |
| transport_security_state_->SetDelegate(NULL); |
| } |
| |
| void TransportSecurityPersister::Initialize( |
| net::TransportSecurityState* state, const FilePath& profile_path) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| transport_security_state_ = state; |
| state_file_ = |
| profile_path.Append(FILE_PATH_LITERAL("TransportSecurity")); |
| state->SetDelegate(this); |
| |
| Task* task = NewRunnableMethod(this, |
| &TransportSecurityPersister::Load); |
| BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, task, 1000); |
| } |
| |
| void TransportSecurityPersister::Load() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| |
| std::string state; |
| if (!file_util::ReadFileToString(state_file_, &state)) |
| return; |
| |
| BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| NewRunnableMethod(this, |
| &TransportSecurityPersister::CompleteLoad, |
| state)); |
| } |
| |
| void TransportSecurityPersister::CompleteLoad(const std::string& state) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| bool dirty = false; |
| if (!transport_security_state_->LoadEntries(state, &dirty)) { |
| LOG(ERROR) << "Failed to deserialize state: " << state; |
| return; |
| } |
| if (dirty) |
| StateIsDirty(transport_security_state_); |
| } |
| |
| void TransportSecurityPersister::StateIsDirty( |
| net::TransportSecurityState* state) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| DCHECK(state == transport_security_state_); |
| |
| if (readonly_) |
| return; |
| |
| if (!save_coalescer_.empty()) |
| return; |
| |
| Task* task = save_coalescer_.NewRunnableMethod( |
| &TransportSecurityPersister::Save); |
| MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 1000); |
| } |
| |
| void TransportSecurityPersister::Save() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| std::string state; |
| if (!transport_security_state_->Serialise(&state)) |
| return; |
| |
| BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| NewRunnableMethod(this, |
| &TransportSecurityPersister::CompleteSave, |
| state)); |
| } |
| |
| void TransportSecurityPersister::CompleteSave(const std::string& state) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| DCHECK(!readonly_); |
| |
| file_util::WriteFile(state_file_, state.data(), state.size()); |
| } |