Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2013 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/net/net_log_temp_file.h"
      6 
      7 #include "base/files/file_util.h"
      8 #include "base/values.h"
      9 #include "chrome/browser/net/chrome_net_log.h"
     10 #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
     11 #include "content/public/browser/browser_thread.h"
     12 #include "net/base/net_log_logger.h"
     13 
     14 using content::BrowserThread;
     15 
     16 NetLogTempFile::NetLogTempFile(ChromeNetLog* chrome_net_log)
     17     : state_(STATE_UNINITIALIZED),
     18       log_type_(LOG_TYPE_NONE),
     19       log_filename_(FILE_PATH_LITERAL("chrome-net-export-log.json")),
     20       chrome_net_log_(chrome_net_log) {
     21 }
     22 
     23 NetLogTempFile::~NetLogTempFile() {
     24   if (net_log_logger_)
     25     net_log_logger_->StopObserving();
     26 }
     27 
     28 void NetLogTempFile::ProcessCommand(Command command) {
     29   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
     30   if (!EnsureInit())
     31     return;
     32 
     33   switch (command) {
     34     case DO_START:
     35       StartNetLog(false);
     36       break;
     37     case DO_START_STRIP_PRIVATE_DATA:
     38       StartNetLog(true);
     39       break;
     40     case DO_STOP:
     41       StopNetLog();
     42       break;
     43     default:
     44       NOTREACHED();
     45       break;
     46   }
     47 }
     48 
     49 base::DictionaryValue* NetLogTempFile::GetState() {
     50   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
     51   base::DictionaryValue* dict = new base::DictionaryValue;
     52 
     53   EnsureInit();
     54 
     55 #ifndef NDEBUG
     56   dict->SetString("file", log_path_.LossyDisplayName());
     57 #endif  // NDEBUG
     58 
     59   switch (state_) {
     60     case STATE_NOT_LOGGING:
     61       dict->SetString("state", "NOT_LOGGING");
     62       break;
     63     case STATE_LOGGING:
     64       dict->SetString("state", "LOGGING");
     65       break;
     66     case STATE_UNINITIALIZED:
     67       dict->SetString("state", "UNINITIALIZED");
     68       break;
     69   }
     70 
     71   switch (log_type_) {
     72     case LOG_TYPE_NONE:
     73       dict->SetString("logType", "NONE");
     74       break;
     75     case LOG_TYPE_UNKNOWN:
     76       dict->SetString("logType", "UNKNOWN");
     77       break;
     78     case LOG_TYPE_NORMAL:
     79       dict->SetString("logType", "NORMAL");
     80       break;
     81     case LOG_TYPE_STRIP_PRIVATE_DATA:
     82       dict->SetString("logType", "STRIP_PRIVATE_DATA");
     83       break;
     84   }
     85 
     86   return dict;
     87 }
     88 
     89 bool NetLogTempFile::EnsureInit() {
     90   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
     91   if (state_ != STATE_UNINITIALIZED)
     92     return true;
     93 
     94   if (!GetNetExportLog())
     95     return false;
     96 
     97   state_ = STATE_NOT_LOGGING;
     98   if (NetExportLogExists())
     99     log_type_ = LOG_TYPE_UNKNOWN;
    100   else
    101     log_type_ = LOG_TYPE_NONE;
    102 
    103   return true;
    104 }
    105 
    106 void NetLogTempFile::StartNetLog(bool strip_private_data) {
    107   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
    108   if (state_ == STATE_LOGGING)
    109     return;
    110 
    111   DCHECK_NE(STATE_UNINITIALIZED, state_);
    112   DCHECK(!log_path_.empty());
    113 
    114   // Try to make sure we can create the file.
    115   // TODO(rtenneti): Find a better for doing the following. Surface some error
    116   // to the user if we couldn't create the file.
    117   FILE* file = base::OpenFile(log_path_, "w");
    118   if (file == NULL)
    119     return;
    120 
    121   scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants());
    122   net_log_logger_.reset(new net::NetLogLogger(file, *constants));
    123   if (strip_private_data) {
    124     net_log_logger_->set_log_level(net::NetLog::LOG_STRIP_PRIVATE_DATA);
    125     log_type_ = LOG_TYPE_STRIP_PRIVATE_DATA;
    126   } else {
    127     log_type_ = LOG_TYPE_NORMAL;
    128   }
    129   net_log_logger_->StartObserving(chrome_net_log_);
    130   state_ = STATE_LOGGING;
    131 }
    132 
    133 void NetLogTempFile::StopNetLog() {
    134   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
    135   if (state_ != STATE_LOGGING)
    136     return;
    137 
    138   net_log_logger_->StopObserving();
    139   net_log_logger_.reset();
    140   state_ = STATE_NOT_LOGGING;
    141 }
    142 
    143 bool NetLogTempFile::GetFilePath(base::FilePath* path) {
    144   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
    145   if (log_type_ == LOG_TYPE_NONE || state_ == STATE_LOGGING)
    146     return false;
    147 
    148   if (!NetExportLogExists())
    149     return false;
    150 
    151   DCHECK(!log_path_.empty());
    152 #if defined(OS_POSIX)
    153   // Users, group and others can read, write and traverse.
    154   int mode = base::FILE_PERMISSION_MASK;
    155   base::SetPosixFilePermissions(log_path_, mode);
    156 #endif  // defined(OS_POSIX)
    157 
    158   *path = log_path_;
    159   return true;
    160 }
    161 
    162 bool NetLogTempFile::GetNetExportLog() {
    163   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
    164   base::FilePath temp_dir;
    165   if (!GetNetExportLogDirectory(&temp_dir))
    166     return false;
    167 
    168   log_path_ = temp_dir.Append(log_filename_);
    169   return true;
    170 }
    171 
    172 bool NetLogTempFile::GetNetExportLogDirectory(base::FilePath* path) {
    173   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
    174   return base::GetTempDir(path);
    175 }
    176 
    177 bool NetLogTempFile::NetExportLogExists() {
    178   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
    179   DCHECK(!log_path_.empty());
    180   return base::PathExists(log_path_);
    181 }
    182