12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/net/net_log_temp_file.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/net/chrome_net_log.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/net_log_logger.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetLogTempFile::NetLogTempFile(ChromeNetLog* chrome_net_log)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : state_(STATE_UNINITIALIZED),
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      log_type_(LOG_TYPE_NONE),
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      log_filename_(FILE_PATH_LITERAL("chrome-net-export-log.json")),
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome_net_log_(chrome_net_log) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetLogTempFile::~NetLogTempFile() {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (net_log_logger_)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net_log_logger_->StopObserving();
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetLogTempFile::ProcessCommand(Command command) {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!EnsureInit())
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (command) {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case DO_START:
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      StartNetLog(false);
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case DO_START_STRIP_PRIVATE_DATA:
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      StartNetLog(true);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case DO_STOP:
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      StopNetLog();
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* NetLogTempFile::GetState() {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnsureInit();
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NDEBUG
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString("file", log_path_.LossyDisplayName());
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // NDEBUG
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (state_) {
6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case STATE_NOT_LOGGING:
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      dict->SetString("state", "NOT_LOGGING");
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case STATE_LOGGING:
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      dict->SetString("state", "LOGGING");
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case STATE_UNINITIALIZED:
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dict->SetString("state", "UNINITIALIZED");
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  switch (log_type_) {
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case LOG_TYPE_NONE:
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      dict->SetString("logType", "NONE");
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case LOG_TYPE_UNKNOWN:
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      dict->SetString("logType", "UNKNOWN");
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case LOG_TYPE_NORMAL:
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      dict->SetString("logType", "NORMAL");
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case LOG_TYPE_STRIP_PRIVATE_DATA:
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      dict->SetString("logType", "STRIP_PRIVATE_DATA");
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dict;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NetLogTempFile::EnsureInit() {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (state_ != STATE_UNINITIALIZED)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetNetExportLog())
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  state_ = STATE_NOT_LOGGING;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NetExportLogExists())
9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    log_type_ = LOG_TYPE_UNKNOWN;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    log_type_ = LOG_TYPE_NONE;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void NetLogTempFile::StartNetLog(bool strip_private_data) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (state_ == STATE_LOGGING)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(STATE_UNINITIALIZED, state_);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!log_path_.empty());
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Try to make sure we can create the file.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(rtenneti): Find a better for doing the following. Surface some error
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to the user if we couldn't create the file.
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FILE* file = base::OpenFile(log_path_, "w");
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (file == NULL)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants());
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net_log_logger_.reset(new net::NetLogLogger(file, *constants));
12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (strip_private_data) {
12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    net_log_logger_->set_log_level(net::NetLog::LOG_STRIP_PRIVATE_DATA);
12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    log_type_ = LOG_TYPE_STRIP_PRIVATE_DATA;
12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    log_type_ = LOG_TYPE_NORMAL;
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net_log_logger_->StartObserving(chrome_net_log_);
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  state_ = STATE_LOGGING;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetLogTempFile::StopNetLog() {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (state_ != STATE_LOGGING)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net_log_logger_->StopObserving();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net_log_logger_.reset();
14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  state_ = STATE_NOT_LOGGING;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NetLogTempFile::GetFilePath(base::FilePath* path) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (log_type_ == LOG_TYPE_NONE || state_ == STATE_LOGGING)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!NetExportLogExists())
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!log_path_.empty());
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_POSIX)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Users, group and others can read, write and traverse.
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int mode = base::FILE_PERMISSION_MASK;
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::SetPosixFilePermissions(log_path_, mode);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(OS_POSIX)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *path = log_path_;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NetLogTempFile::GetNetExportLog() {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath temp_dir;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetNetExportLogDirectory(&temp_dir))
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  log_path_ = temp_dir.Append(log_filename_);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NetLogTempFile::GetNetExportLogDirectory(base::FilePath* path) {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return base::GetTempDir(path);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NetLogTempFile::NetExportLogExists() {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!log_path_.empty());
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return base::PathExists(log_path_);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
182