1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/transport_security_persister.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/transport_security_state.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTransportSecurityPersister::TransportSecurityPersister(bool readonly)
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  : ALLOW_THIS_IN_INITIALIZER_LIST(save_coalescer_(this)),
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    readonly_(readonly) {
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTransportSecurityPersister::~TransportSecurityPersister() {
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  transport_security_state_->SetDelegate(NULL);
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TransportSecurityPersister::Initialize(
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net::TransportSecurityState* state, const FilePath& profile_path) {
26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  transport_security_state_ = state;
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  state_file_ =
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_path.Append(FILE_PATH_LITERAL("TransportSecurity"));
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  state->SetDelegate(this);
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Task* task = NewRunnableMethod(this,
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &TransportSecurityPersister::Load);
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, task, 1000);
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TransportSecurityPersister::Load() {
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string state;
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!file_util::ReadFileToString(state_file_, &state))
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(this,
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        &TransportSecurityPersister::CompleteLoad,
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        state));
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TransportSecurityPersister::CompleteLoad(const std::string& state) {
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool dirty = false;
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!transport_security_state_->LoadEntries(state, &dirty)) {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Failed to deserialize state: " << state;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (dirty)
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    StateIsDirty(transport_security_state_);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TransportSecurityPersister::StateIsDirty(
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net::TransportSecurityState* state) {
64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(state == transport_security_state_);
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (readonly_)
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!save_coalescer_.empty())
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Task* task = save_coalescer_.NewRunnableMethod(
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &TransportSecurityPersister::Save);
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 1000);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TransportSecurityPersister::Save() {
79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string state;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!transport_security_state_->Serialise(&state))
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(this,
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        &TransportSecurityPersister::CompleteSave,
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        state));
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TransportSecurityPersister::CompleteSave(const std::string& state) {
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!readonly_);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  file_util::WriteFile(state_file_, state.data(), state.size());
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
97