Coverage for /Syzygy/kasko/api/reporter.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
84.3%70830.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/kasko/api/reporter.h"
  16    :  
  17    :  #include <stdint.h>
  18    :  
  19    :  #include <map>
  20    :  #include <vector>
  21    :  
  22    :  #include "base/bind.h"
  23    :  #include "base/bind_helpers.h"
  24    :  #include "base/environment.h"
  25    :  #include "base/logging.h"
  26    :  #include "base/files/file_path.h"
  27    :  #include "base/memory/scoped_ptr.h"
  28    :  #include "base/strings/string_number_conversions.h"
  29    :  #include "base/time/time.h"
  30    :  #include "base/win/scoped_handle.h"
  31    :  #include "syzygy/kasko/dll_lifetime.h"
  32    :  #include "syzygy/kasko/minidump.h"
  33    :  #include "syzygy/kasko/minidump_request.h"
  34    :  #include "syzygy/kasko/reporter.h"
  35    :  #include "syzygy/kasko/api/crash_key.h"
  36    :  #include "syzygy/kasko/api/internal/crash_key_registration.h"
  37    :  
  38    :  namespace kasko {
  39    :  namespace api {
  40    :  namespace {
  41    :  
  42    :  // Default upload and retry times. These can be overridden by an environment
  43    :  // variable.
  44    :  const uint16_t kDefaultUploadDelayInSeconds = 180;
  45    :  const uint16_t kDefaultRetryIntervalInMinutes = 180;
  46    :  
  47    :  // Environment variables for overriding the above times.
  48    :  const char kEnvUploadDelayInSeconds[] = "KASKO_UPLOAD_DELAY_IN_SECONDS";
  49    :  const char kEnvRetryIntervalInMinutes[] = "KASKO_RETRY_INTERVAL_IN_MINUTES";
  50    :  
  51    :  const DllLifetime* g_dll_lifetime;
  52    :  Reporter* g_reporter;
  53    :  
  54    :  void InvokeOnUploadProc(
  55    :      OnUploadProc* on_upload_proc,
  56    :      void* on_upload_context,
  57    :      const base::string16& report_id,
  58    :      const base::FilePath& minidump_path,
  59  E :      const std::map<base::string16, base::string16>& crash_keys) {
  60  E :    std::vector<const base::char16*> crash_key_names;
  61  E :    std::vector<const base::char16*> crash_key_values;
  62  E :    crash_key_names.reserve(crash_keys.size() + 1);
  63  E :    crash_key_values.reserve(crash_keys.size() + 1);
  64    :  
  65  E :    for (const auto& entry : crash_keys) {
  66  E :      crash_key_names.push_back(entry.first.c_str());
  67  E :      crash_key_values.push_back(entry.second.c_str());
  68  E :    }
  69  E :    crash_key_names.push_back(nullptr);
  70  E :    crash_key_values.push_back(nullptr);
  71    :  
  72    :    on_upload_proc(on_upload_context, report_id.c_str(),
  73    :                   minidump_path.value().c_str(), crash_key_names.data(),
  74  E :                   crash_key_values.data());
  75  E :  }
  76    :  
  77    :  // Returns an integer value from the environment. If not present or malformed,
  78    :  // returns the specified default. Only allows positive values.
  79    :  int64_t GetIntegerFromEnvironment(const char* key_name,
  80  E :                                    int64_t default_value) {
  81  E :    scoped_ptr<base::Environment> env(base::Environment::Create());
  82  E :    std::string value;
  83  E :    if (!env->GetVar(key_name, &value))
  84  E :      return default_value;
  85    :  
  86  i :    int64_t i = 0;
  87  i :    if (!base::StringToInt64(value, &i))
  88  i :      return default_value;
  89    :  
  90  i :    if (i <= 0)
  91  i :      return default_value;
  92    :  
  93  i :    return i;
  94  E :  }
  95    :  
  96    :  }  // namespace
  97    :  
  98    :  const base::char16* const kPermanentFailureCrashKeysExtension =
  99  E :      Reporter::kPermanentFailureCrashKeysExtension;
 100    :  const base::char16* const kPermanentFailureMinidumpExtension =
 101  E :      Reporter::kPermanentFailureMinidumpExtension;
 102    :  
 103    :  bool InitializeReporter(const base::char16* endpoint_name,
 104    :                          const base::char16* url,
 105    :                          const base::char16* data_directory,
 106    :                          const base::char16* permanent_failure_directory,
 107    :                          OnUploadProc* on_upload_proc,
 108  E :                          void* on_upload_context) {
 109  E :    DCHECK(!g_dll_lifetime);
 110  E :    g_dll_lifetime = new DllLifetime;
 111    :  
 112  E :    Reporter::OnUploadCallback on_upload_callback;
 113    :  
 114  E :    if (on_upload_proc) {
 115    :      on_upload_callback =
 116    :          base::Bind(&InvokeOnUploadProc, base::Unretained(on_upload_proc),
 117  E :                     base::Unretained(on_upload_context));
 118    :    }
 119    :  
 120    :  
 121    :    int64_t upload_delay = GetIntegerFromEnvironment(
 122  E :        kEnvUploadDelayInSeconds, kDefaultUploadDelayInSeconds);
 123    :    int64_t retry_interval = GetIntegerFromEnvironment(
 124  E :        kEnvRetryIntervalInMinutes, kDefaultRetryIntervalInMinutes);
 125  E :    DCHECK(!g_reporter);
 126    :    g_reporter =
 127    :        Reporter::Create(endpoint_name, url, base::FilePath(data_directory),
 128    :                         base::FilePath(permanent_failure_directory),
 129    :                         base::TimeDelta::FromSeconds(upload_delay),
 130    :                         base::TimeDelta::FromMinutes(retry_interval),
 131    :                         on_upload_callback)
 132  E :            .release();
 133    :  
 134  E :    return g_reporter != nullptr;
 135  E :  }
 136    :  
 137    :  void SendReportForProcess(base::ProcessHandle process_handle,
 138    :                            base::PlatformThreadId thread_id,
 139    :                            const EXCEPTION_POINTERS* exception_pointers,
 140    :                            MinidumpType minidump_type,
 141    :                            const base::char16* const* keys,
 142  E :                            const base::char16* const* values) {
 143  E :    DCHECK(g_reporter);
 144  E :    if (!g_reporter)
 145  i :      return;
 146  E :    DCHECK_EQ(keys == nullptr, values == nullptr);
 147    :  
 148  E :    MinidumpRequest request;
 149    :  
 150    :    request.exception_info_address =
 151  E :        reinterpret_cast<uint32_t>(exception_pointers);
 152    :  
 153  E :    if (keys != nullptr && values != nullptr) {
 154  E :      size_t i = 0;
 155  E :      for (; keys[i] && values[i]; ++i) {
 156  E :        if (keys[i][0] == 0 || values[i][0] == 0)
 157  E :          continue;
 158    :        request.crash_keys.push_back(
 159  E :            MinidumpRequest::CrashKey(keys[i], values[i]));
 160  E :      }
 161  E :      DCHECK(!keys[i]);
 162  E :      DCHECK(!values[i]);
 163    :    }
 164    :  
 165    :    // Reopen the process handle with the necessary access level to read memory
 166    :    // and create a minidump.
 167    :    base::win::ScopedHandle augmented_process_handle(
 168    :        ::OpenProcess(GetRequiredAccessForMinidumpType(minidump_type), FALSE,
 169  E :                      base::GetProcId(process_handle)));
 170  E :    if (!augmented_process_handle.IsValid())
 171  i :      return;
 172    :  
 173  E :    std::vector<CrashKey> registered_crash_keys;
 174    :    if (internal::ReadCrashKeysFromProcess(augmented_process_handle.Get(),
 175  E :                                           &registered_crash_keys)) {
 176  E :      for (auto& crash_key : registered_crash_keys) {
 177  E :        if (crash_key.name[0] == 0 || crash_key.value[0] == 0)
 178  E :          continue;
 179    :        request.crash_keys.push_back(
 180  E :            MinidumpRequest::CrashKey(crash_key.name, crash_key.value));
 181  E :      }
 182    :    }
 183    :  
 184  E :    switch (minidump_type) {
 185    :      case SMALL_DUMP_TYPE:
 186  E :        request.type = MinidumpRequest::SMALL_DUMP_TYPE;
 187  E :        break;
 188    :      case LARGER_DUMP_TYPE:
 189  i :        request.type = MinidumpRequest::LARGER_DUMP_TYPE;
 190  i :        break;
 191    :      case FULL_DUMP_TYPE:
 192  i :        request.type = MinidumpRequest::FULL_DUMP_TYPE;
 193  i :        break;
 194    :      default:
 195  i :        NOTREACHED();
 196    :        break;
 197    :    }
 198    :  
 199    :    g_reporter->SendReportForProcess(augmented_process_handle.Get(), thread_id,
 200  E :                                     request);
 201  E :  }
 202    :  
 203  E :  void ShutdownReporter() {
 204  E :    scoped_ptr<Reporter> reporter(g_reporter);
 205  E :    g_reporter = nullptr;
 206  E :    Reporter::Shutdown(reporter.Pass());
 207    :  
 208  E :    DCHECK(g_dll_lifetime);
 209  E :    delete g_dll_lifetime;
 210  E :    g_dll_lifetime = nullptr;
 211  E :  }
 212    :  
 213    :  }  // namespace api
 214    :  }  // namespace kasko

Coverage information generated Thu Jan 14 17:40:38 2016.