// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//------------------------------------------------------------------------------
// Description of the life cycle of a instance of MetricsService.
//
//  OVERVIEW
//
// A MetricsService instance is created at ChromeFrame startup in
// the IE process. It is the central controller for the UMA log data.
// Its major job is to manage logs, prepare them for transmission.
// Currently only histogram data is tracked in log.  When MetricsService
// prepares log for submission it snapshots the current stats of histograms,
// translates log to a protocol buffer.  Transmission includes submitting a
// compressed log as data in a URL-get, and is performed using functionality
// provided by Urlmon
// The actual transmission is performed using a windows timer procedure which
// basically means that the thread on which the MetricsService object is
// instantiated needs a message pump. Also on IE7 where every tab is created
// on its own thread we would have a case where the timer procedures can
// compete for sending histograms.
//
// When preparing log for submission we acquire a list of all local histograms
// that have been flagged for upload to the UMA server.
//
// When ChromeFrame shuts down, there will typically be a fragment of an ongoing
// log that has not yet been transmitted.  Currently this data is ignored.
//
// With the above overview, we can now describe the state machine's various
// stats, based on the State enum specified in the state_ member.  Those states
// are:
//
//    INITIALIZED,      // Constructor was called.
//    ACTIVE,           // Accumalating log data.
//    STOPPED,          // Service has stopped.
//
//-----------------------------------------------------------------------------

#include "chrome_frame/metrics_service.h"

#include <atlbase.h>
#include <atlwin.h>
#include <objbase.h>
#include <windows.h>

#include "base/metrics/statistics_recorder.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/win/scoped_comptr.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/metrics/metrics_log_base.h"
#include "chrome/common/metrics/metrics_log_manager.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_settings.h"
#include "chrome_frame/bind_status_callback_impl.h"
#include "chrome_frame/crash_reporting/crash_metrics.h"
#include "chrome_frame/html_utils.h"
#include "chrome_frame/utils.h"

using base::Time;
using base::TimeDelta;
using base::win::ScopedComPtr;

// The first UMA upload occurs after this interval.
static const int kInitialUMAUploadTimeoutMilliSeconds = 30000;

// Default to one UMA upload per 10 mins.
static const int kMinMilliSecondsPerUMAUpload = 600000;

base::LazyInstance<base::ThreadLocalPointer<MetricsService> >
    MetricsService::g_metrics_instance_ = LAZY_INSTANCE_INITIALIZER;

std::string MetricsService::client_id_;

base::Lock MetricsService::metrics_service_lock_;

// This class provides functionality to upload the ChromeFrame UMA data to the
// server. An instance of this class is created whenever we have data to be
// uploaded to the server.
class ChromeFrameMetricsDataUploader : public BSCBImpl {
 public:
  ChromeFrameMetricsDataUploader()
      : cache_stream_(NULL),
        upload_data_size_(0) {
    DVLOG(1) << __FUNCTION__;
  }

  ~ChromeFrameMetricsDataUploader() {
    DVLOG(1) << __FUNCTION__;
  }

  static HRESULT ChromeFrameMetricsDataUploader::UploadDataHelper(
      const std::string& upload_data,
      const std::string& server_url,
      const std::string& mime_type) {
    CComObject<ChromeFrameMetricsDataUploader>* data_uploader = NULL;
    CComObject<ChromeFrameMetricsDataUploader>::CreateInstance(&data_uploader);
    DCHECK(data_uploader != NULL);

    data_uploader->AddRef();
    HRESULT hr = data_uploader->UploadData(upload_data, server_url, mime_type);
    if (FAILED(hr)) {
      DLOG(ERROR) << "Failed to initialize ChromeFrame UMA data uploader: Err"
                  << hr;
    }
    data_uploader->Release();
    return hr;
  }

  HRESULT UploadData(const std::string& upload_data,
                     const std::string& server_url,
                     const std::string& mime_type) {
    if (upload_data.empty()) {
      NOTREACHED() << "Invalid upload data";
      return E_INVALIDARG;
    }

    DCHECK(cache_stream_.get() == NULL);

    upload_data_size_ = upload_data.size() + 1;

    HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, cache_stream_.Receive());
    if (FAILED(hr)) {
      NOTREACHED() << "Failed to create stream. Error:"
                   << hr;
      return hr;
    }

    DCHECK(cache_stream_.get());

    unsigned long written = 0;
    cache_stream_->Write(upload_data.c_str(), upload_data_size_, &written);
    DCHECK(written == upload_data_size_);

    RewindStream(cache_stream_);

    server_url_ = ASCIIToWide(server_url);
    mime_type_ = mime_type;
    DCHECK(!server_url_.empty());
    DCHECK(!mime_type_.empty());

    hr = CreateURLMoniker(NULL, server_url_.c_str(),
                          upload_moniker_.Receive());
    if (FAILED(hr)) {
      DLOG(ERROR) << "Failed to create url moniker for url:"
                  << server_url_.c_str()
                  << " Error:"
                  << hr;
    } else {
      ScopedComPtr<IBindCtx> context;
      hr = CreateAsyncBindCtx(0, this, NULL, context.Receive());
      DCHECK(SUCCEEDED(hr));
      DCHECK(context);

      ScopedComPtr<IStream> stream;
      hr = upload_moniker_->BindToStorage(
          context, NULL, IID_IStream,
          reinterpret_cast<void**>(stream.Receive()));
      if (FAILED(hr)) {
        NOTREACHED();
        DLOG(ERROR) << "Failed to bind to upload data moniker. Error:"
                    << hr;
      }
    }
    return hr;
  }

  STDMETHOD(BeginningTransaction)(LPCWSTR url, LPCWSTR headers, DWORD reserved,
                                  LPWSTR* additional_headers) {
    std::string new_headers;
    new_headers =
        base::StringPrintf(
            "Content-Length: %s\r\n"
            "Content-Type: %s\r\n"
            "%s\r\n",
            base::Int64ToString(upload_data_size_).c_str(),
            mime_type_.c_str(),
            http_utils::GetDefaultUserAgentHeaderWithCFTag().c_str());

    *additional_headers = reinterpret_cast<wchar_t*>(
        CoTaskMemAlloc((new_headers.size() + 1) * sizeof(wchar_t)));

    lstrcpynW(*additional_headers, ASCIIToWide(new_headers).c_str(),
              new_headers.size());

    return BSCBImpl::BeginningTransaction(url, headers, reserved,
                                          additional_headers);
  }

  STDMETHOD(GetBindInfo)(DWORD* bind_flags, BINDINFO* bind_info) {
    if ((bind_info == NULL) || (bind_info->cbSize == 0) ||
        (bind_flags == NULL))
      return E_INVALIDARG;

    *bind_flags = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
    // Bypass caching proxies on POSTs and PUTs and avoid writing responses to
    // these requests to the browser's cache
    *bind_flags |= BINDF_GETNEWESTVERSION | BINDF_PRAGMA_NO_CACHE;

    DCHECK(cache_stream_.get());

    // Initialize the STGMEDIUM.
    memset(&bind_info->stgmedData, 0, sizeof(STGMEDIUM));
    bind_info->grfBindInfoF = 0;
    bind_info->szCustomVerb = NULL;
    bind_info->dwBindVerb = BINDVERB_POST;
    bind_info->stgmedData.tymed = TYMED_ISTREAM;
    bind_info->stgmedData.pstm = cache_stream_.get();
    bind_info->stgmedData.pstm->AddRef();
    return BSCBImpl::GetBindInfo(bind_flags, bind_info);
  }

  STDMETHOD(OnResponse)(DWORD response_code, LPCWSTR response_headers,
                        LPCWSTR request_headers, LPWSTR* additional_headers) {
    DVLOG(1) << __FUNCTION__ << " headers: \n" << response_headers;
    return BSCBImpl::OnResponse(response_code, response_headers,
                                request_headers, additional_headers);
  }

 private:
  std::wstring server_url_;
  std::string mime_type_;
  size_t upload_data_size_;
  ScopedComPtr<IStream> cache_stream_;
  ScopedComPtr<IMoniker> upload_moniker_;
};

MetricsService* MetricsService::GetInstance() {
  if (g_metrics_instance_.Pointer()->Get())
    return g_metrics_instance_.Pointer()->Get();

  g_metrics_instance_.Pointer()->Set(new MetricsService);
  return g_metrics_instance_.Pointer()->Get();
}

MetricsService::MetricsService()
    : recording_active_(false),
      reporting_active_(false),
      user_permits_upload_(false),
      state_(INITIALIZED),
      thread_(NULL),
      initial_uma_upload_(true),
      transmission_timer_id_(0) {
}

MetricsService::~MetricsService() {
  SetRecording(false);
}

void MetricsService::InitializeMetricsState() {
  DCHECK(state_ == INITIALIZED);

  thread_ = base::PlatformThread::CurrentId();

  user_permits_upload_ = GoogleUpdateSettings::GetCollectStatsConsent();
  // Update session ID
  session_id_ = CrashMetricsReporter::GetInstance()->IncrementMetric(
      CrashMetricsReporter::SESSION_ID);

  base::StatisticsRecorder::Initialize();
  CrashMetricsReporter::GetInstance()->set_active(true);
}

// static
void MetricsService::Start() {
  base::AutoLock lock(metrics_service_lock_);

  if (GetInstance()->state_ == ACTIVE)
    return;

  GetInstance()->InitializeMetricsState();
  GetInstance()->SetRecording(true);
  GetInstance()->SetReporting(true);
}

// static
void MetricsService::Stop() {
  base::AutoLock lock(metrics_service_lock_);

  GetInstance()->SetReporting(false);
  GetInstance()->SetRecording(false);
}

void MetricsService::SetRecording(bool enabled) {
  DCHECK_EQ(thread_, base::PlatformThread::CurrentId());
  if (enabled == recording_active_)
    return;

  if (enabled) {
    StartRecording();
  } else {
    state_ = STOPPED;
  }
  recording_active_ = enabled;
}

// static
const std::string& MetricsService::GetClientID() {
  // TODO(robertshield): Chrome Frame shouldn't generate a new ID on every run
  // as this apparently breaks some assumptions during metric analysis.
  // See http://crbug.com/117188
  if (client_id_.empty()) {
    const int kGUIDSize = 39;

    GUID guid;
    HRESULT guid_result = CoCreateGuid(&guid);
    DCHECK(SUCCEEDED(guid_result));

    string16 guid_string;
    int result = StringFromGUID2(guid,
                                 WriteInto(&guid_string, kGUIDSize), kGUIDSize);
    DCHECK(result == kGUIDSize);
    client_id_ = WideToUTF8(guid_string.substr(1, guid_string.length() - 2));
  }
  return client_id_;
}

// static
void CALLBACK MetricsService::TransmissionTimerProc(HWND window,
                                                    unsigned int message,
                                                    unsigned int event_id,
                                                    unsigned int time) {
  DVLOG(1) << "Transmission timer notified";
  DCHECK(GetInstance() != NULL);
  GetInstance()->UploadData();
  if (GetInstance()->initial_uma_upload_) {
    // If this is the first uma upload by this process then subsequent uma
    // uploads should occur once every 10 minutes(default).
    GetInstance()->initial_uma_upload_ = false;
    DCHECK(GetInstance()->transmission_timer_id_ != 0);
    SetTimer(NULL, GetInstance()->transmission_timer_id_,
             kMinMilliSecondsPerUMAUpload,
             reinterpret_cast<TIMERPROC>(TransmissionTimerProc));
  }
}

void MetricsService::SetReporting(bool enable) {
  static const int kChromeFrameMetricsTimerId = 0xFFFFFFFF;

  DCHECK_EQ(thread_, base::PlatformThread::CurrentId());
  if (reporting_active_ != enable) {
    reporting_active_ = enable;
    if (reporting_active_) {
      transmission_timer_id_ =
          SetTimer(NULL, kChromeFrameMetricsTimerId,
                   kInitialUMAUploadTimeoutMilliSeconds,
                   reinterpret_cast<TIMERPROC>(TransmissionTimerProc));
    } else {
      UploadData();
    }
  }
}

//------------------------------------------------------------------------------
// Recording control methods

void MetricsService::StartRecording() {
  DCHECK_EQ(thread_, base::PlatformThread::CurrentId());
  if (log_manager_.current_log())
    return;

  MetricsLogManager::LogType log_type = (state_ == INITIALIZED) ?
      MetricsLogManager::INITIAL_LOG : MetricsLogManager::ONGOING_LOG;
  log_manager_.BeginLoggingWithLog(new MetricsLogBase(GetClientID(),
                                                      session_id_,
                                                      GetVersionString()),
                                   log_type);
  if (state_ == INITIALIZED)
    state_ = ACTIVE;
}

void MetricsService::StopRecording(bool save_log) {
  DCHECK_EQ(thread_, base::PlatformThread::CurrentId());
  if (!log_manager_.current_log())
    return;

  // Put incremental histogram deltas at the end of all log transmissions.
  // Don't bother if we're going to discard current_log.
  if (save_log) {
    CrashMetricsReporter::GetInstance()->RecordCrashMetrics();
    RecordCurrentHistograms();
  }

  if (save_log) {
    log_manager_.FinishCurrentLog();
    log_manager_.StageNextLogForUpload();
  } else {
    log_manager_.DiscardCurrentLog();
  }
}

void MetricsService::MakePendingLog() {
  DCHECK_EQ(thread_, base::PlatformThread::CurrentId());
  if (log_manager_.has_staged_log())
    return;

  if (state_ != ACTIVE) {
    NOTREACHED();
    return;
  }

  StopRecording(true);
  StartRecording();
}

bool MetricsService::TransmissionPermitted() const {
  // If the user forbids uploading that's their business, and we don't upload
  // anything.
  return user_permits_upload_;
}

bool MetricsService::UploadData() {
  DCHECK_EQ(thread_, base::PlatformThread::CurrentId());

  if (!GetInstance()->TransmissionPermitted())
    return false;

  static long currently_uploading = 0;
  if (InterlockedCompareExchange(&currently_uploading, 1, 0)) {
    DVLOG(1) << "Contention for uploading metrics data. Backing off";
    return false;
  }

  MakePendingLog();

  bool ret = true;

  if (log_manager_.has_staged_log()) {
    HRESULT hr = ChromeFrameMetricsDataUploader::UploadDataHelper(
        log_manager_.staged_log_text(), kServerUrl, kMimeType);
    DCHECK(SUCCEEDED(hr));
    log_manager_.DiscardStagedLog();
  } else {
    NOTREACHED();
    ret = false;
  }

  currently_uploading = 0;
  return ret;
}

// static
std::string MetricsService::GetVersionString() {
  chrome::VersionInfo version_info;
  if (version_info.is_valid()) {
    std::string version = version_info.Version();
    // Add the -F extensions to ensure that UMA data uploaded by ChromeFrame
    // lands in the ChromeFrame bucket.
    version += "-F";
    if (!version_info.IsOfficialBuild())
      version.append("-devel");
    return version;
  } else {
    NOTREACHED() << "Unable to retrieve version string.";
  }

  return std::string();
}
