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
TransportSecurityPersister(bool readonly)15 TransportSecurityPersister::TransportSecurityPersister(bool readonly)
16 : ALLOW_THIS_IN_INITIALIZER_LIST(save_coalescer_(this)),
17 readonly_(readonly) {
18 }
19
~TransportSecurityPersister()20 TransportSecurityPersister::~TransportSecurityPersister() {
21 transport_security_state_->SetDelegate(NULL);
22 }
23
Initialize(net::TransportSecurityState * state,const FilePath & profile_path)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
Load()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
CompleteLoad(const std::string & state)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
StateIsDirty(net::TransportSecurityState * state)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
Save()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
CompleteSave(const std::string & state)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