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_filename_(FILE_PATH_LITERAL("chrome-net-export-log.json")), 19 chrome_net_log_(chrome_net_log) { 20 } 21 22 NetLogTempFile::~NetLogTempFile() { 23 if (net_log_logger_) 24 net_log_logger_->StopObserving(); 25 } 26 27 void NetLogTempFile::ProcessCommand(Command command) { 28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 29 if (!EnsureInit()) 30 return; 31 32 switch (command) { 33 case DO_START: 34 StartNetLog(); 35 break; 36 case DO_STOP: 37 StopNetLog(); 38 break; 39 default: 40 NOTREACHED(); 41 break; 42 } 43 } 44 45 DictionaryValue* NetLogTempFile::GetState() { 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 47 base::DictionaryValue* dict = new base::DictionaryValue; 48 49 EnsureInit(); 50 51 #ifndef NDEBUG 52 dict->SetString("file", log_path_.LossyDisplayName()); 53 #endif // NDEBUG 54 55 switch (state_) { 56 case STATE_ALLOW_START: 57 dict->SetString("state", "ALLOW_START"); 58 break; 59 case STATE_ALLOW_STOP: 60 dict->SetString("state", "ALLOW_STOP"); 61 break; 62 case STATE_ALLOW_START_SEND: 63 dict->SetString("state", "ALLOW_START_SEND"); 64 break; 65 default: 66 dict->SetString("state", "UNINITIALIZED"); 67 break; 68 } 69 return dict; 70 } 71 72 bool NetLogTempFile::EnsureInit() { 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 74 if (state_ != STATE_UNINITIALIZED) 75 return true; 76 77 if (!GetNetExportLog()) 78 return false; 79 80 if (NetExportLogExists()) 81 state_ = STATE_ALLOW_START_SEND; 82 else 83 state_ = STATE_ALLOW_START; 84 85 return true; 86 } 87 88 void NetLogTempFile::StartNetLog() { 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 90 if (state_ == STATE_ALLOW_STOP) 91 return; 92 93 DCHECK_NE(STATE_UNINITIALIZED, state_); 94 DCHECK(!log_path_.empty()); 95 96 // Try to make sure we can create the file. 97 // TODO(rtenneti): Find a better for doing the following. Surface some error 98 // to the user if we couldn't create the file. 99 FILE* file = base::OpenFile(log_path_, "w"); 100 if (file == NULL) 101 return; 102 103 scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants()); 104 net_log_logger_.reset(new net::NetLogLogger(file, *constants)); 105 net_log_logger_->StartObserving(chrome_net_log_); 106 state_ = STATE_ALLOW_STOP; 107 } 108 109 void NetLogTempFile::StopNetLog() { 110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 111 if (state_ != STATE_ALLOW_STOP) 112 return; 113 114 net_log_logger_->StopObserving(); 115 net_log_logger_.reset(); 116 state_ = STATE_ALLOW_START_SEND; 117 } 118 119 bool NetLogTempFile::GetFilePath(base::FilePath* path) { 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 121 if (state_ != STATE_ALLOW_START_SEND) 122 return false; 123 124 if (!NetExportLogExists()) 125 return false; 126 127 DCHECK(!log_path_.empty()); 128 #if defined(OS_POSIX) 129 // Users, group and others can read, write and traverse. 130 int mode = base::FILE_PERMISSION_MASK; 131 base::SetPosixFilePermissions(log_path_, mode); 132 #endif // defined(OS_POSIX) 133 134 *path = log_path_; 135 return true; 136 } 137 138 bool NetLogTempFile::GetNetExportLog() { 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 140 base::FilePath temp_dir; 141 if (!GetNetExportLogDirectory(&temp_dir)) 142 return false; 143 144 log_path_ = temp_dir.Append(log_filename_); 145 return true; 146 } 147 148 bool NetLogTempFile::GetNetExportLogDirectory(base::FilePath* path) { 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 150 return base::GetTempDir(path); 151 } 152 153 bool NetLogTempFile::NetExportLogExists() { 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)); 155 DCHECK(!log_path_.empty()); 156 return base::PathExists(log_path_); 157 } 158