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 #include "chrome/browser/transport_security_persister.h" 6 7 #include "base/file_path.h" 8 #include "base/file_util.h" 9 #include "base/message_loop.h" 10 #include "base/path_service.h" 11 #include "chrome/common/chrome_paths.h" 12 #include "content/browser/browser_thread.h" 13 #include "net/base/transport_security_state.h" 14 15 TransportSecurityPersister::TransportSecurityPersister(bool readonly) 16 : ALLOW_THIS_IN_INITIALIZER_LIST(save_coalescer_(this)), 17 readonly_(readonly) { 18 } 19 20 TransportSecurityPersister::~TransportSecurityPersister() { 21 transport_security_state_->SetDelegate(NULL); 22 } 23 24 void TransportSecurityPersister::Initialize( 25 net::TransportSecurityState* state, const FilePath& profile_path) { 26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 27 transport_security_state_ = state; 28 state_file_ = 29 profile_path.Append(FILE_PATH_LITERAL("TransportSecurity")); 30 state->SetDelegate(this); 31 32 Task* task = NewRunnableMethod(this, 33 &TransportSecurityPersister::Load); 34 BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, task, 1000); 35 } 36 37 void TransportSecurityPersister::Load() { 38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 39 40 std::string state; 41 if (!file_util::ReadFileToString(state_file_, &state)) 42 return; 43 44 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 45 NewRunnableMethod(this, 46 &TransportSecurityPersister::CompleteLoad, 47 state)); 48 } 49 50 void TransportSecurityPersister::CompleteLoad(const std::string& state) { 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 52 53 bool dirty = false; 54 if (!transport_security_state_->LoadEntries(state, &dirty)) { 55 LOG(ERROR) << "Failed to deserialize state: " << state; 56 return; 57 } 58 if (dirty) 59 StateIsDirty(transport_security_state_); 60 } 61 62 void TransportSecurityPersister::StateIsDirty( 63 net::TransportSecurityState* state) { 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 65 DCHECK(state == transport_security_state_); 66 67 if (readonly_) 68 return; 69 70 if (!save_coalescer_.empty()) 71 return; 72 73 Task* task = save_coalescer_.NewRunnableMethod( 74 &TransportSecurityPersister::Save); 75 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 1000); 76 } 77 78 void TransportSecurityPersister::Save() { 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 80 81 std::string state; 82 if (!transport_security_state_->Serialise(&state)) 83 return; 84 85 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 86 NewRunnableMethod(this, 87 &TransportSecurityPersister::CompleteSave, 88 state)); 89 } 90 91 void TransportSecurityPersister::CompleteSave(const std::string& state) { 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 93 DCHECK(!readonly_); 94 95 file_util::WriteFile(state_file_, state.data(), state.size()); 96 } 97