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/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