Home | History | Annotate | Download | only in browser
      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