| Index: trace_event/trace_config.cc
 | 
| diff --git a/trace_event/trace_config.cc b/trace_event/trace_config.cc
 | 
| index 23c8cfff718f2db6eab463dfe05632742eea08b0..8f0f1c4c21ad8ffd47f805a6f1da44a29f8bbdba 100644
 | 
| --- a/trace_event/trace_config.cc
 | 
| +++ b/trace_event/trace_config.cc
 | 
| @@ -10,6 +10,7 @@
 | 
|  #include "base/strings/string_split.h"
 | 
|  #include "base/strings/string_tokenizer.h"
 | 
|  #include "base/strings/stringprintf.h"
 | 
| +#include "base/trace_event/memory_dump_manager.h"
 | 
|  #include "base/trace_event/trace_event.h"
 | 
|  
 | 
|  namespace base {
 | 
| @@ -37,6 +38,23 @@ const char kSyntheticDelaysParam[] = "synthetic_delays";
 | 
|  
 | 
|  const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY(";
 | 
|  
 | 
| +// String parameters that is used to parse memory dump config in trace config
 | 
| +// string.
 | 
| +const char kMemoryDumpConfigParam[] = "memory_dump_config";
 | 
| +const char kTriggersParam[] = "triggers";
 | 
| +const char kPeriodicIntervalParam[] = "periodic_interval_ms";
 | 
| +const char kModeParam[] = "mode";
 | 
| +const char kDetailedParam[] = "detailed";
 | 
| +const char kLightParam[] = "light";
 | 
| +
 | 
| +// Default configuration of memory dumps.
 | 
| +const TraceConfig::MemoryDumpTriggerConfig kDefaultHeavyMemoryDumpTrigger = {
 | 
| +    2000,  // periodic_interval_ms
 | 
| +    MemoryDumpArgs::LevelOfDetail::HIGH};
 | 
| +const TraceConfig::MemoryDumpTriggerConfig kDefaultLightMemoryDumpTrigger = {
 | 
| +    250,  // periodic_interval_ms
 | 
| +    MemoryDumpArgs::LevelOfDetail::LOW};
 | 
| +
 | 
|  }  // namespace
 | 
|  
 | 
|  TraceConfig::TraceConfig() {
 | 
| @@ -82,11 +100,11 @@ TraceConfig::TraceConfig(const TraceConfig& tc)
 | 
|        enable_sampling_(tc.enable_sampling_),
 | 
|        enable_systrace_(tc.enable_systrace_),
 | 
|        enable_argument_filter_(tc.enable_argument_filter_),
 | 
| +      memory_dump_config_(tc.memory_dump_config_),
 | 
|        included_categories_(tc.included_categories_),
 | 
|        disabled_categories_(tc.disabled_categories_),
 | 
|        excluded_categories_(tc.excluded_categories_),
 | 
| -      synthetic_delays_(tc.synthetic_delays_) {
 | 
| -}
 | 
| +      synthetic_delays_(tc.synthetic_delays_) {}
 | 
|  
 | 
|  TraceConfig::~TraceConfig() {
 | 
|  }
 | 
| @@ -99,6 +117,7 @@ TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) {
 | 
|    enable_sampling_ = rhs.enable_sampling_;
 | 
|    enable_systrace_ = rhs.enable_systrace_;
 | 
|    enable_argument_filter_ = rhs.enable_argument_filter_;
 | 
| +  memory_dump_config_ = rhs.memory_dump_config_;
 | 
|    included_categories_ = rhs.included_categories_;
 | 
|    disabled_categories_ = rhs.disabled_categories_;
 | 
|    excluded_categories_ = rhs.excluded_categories_;
 | 
| @@ -207,6 +226,10 @@ void TraceConfig::Merge(const TraceConfig& config) {
 | 
|      included_categories_.clear();
 | 
|    }
 | 
|  
 | 
| +  memory_dump_config_.insert(memory_dump_config_.end(),
 | 
| +                             config.memory_dump_config_.begin(),
 | 
| +                             config.memory_dump_config_.end());
 | 
| +
 | 
|    disabled_categories_.insert(disabled_categories_.end(),
 | 
|                                config.disabled_categories_.begin(),
 | 
|                                config.disabled_categories_.end());
 | 
| @@ -227,6 +250,7 @@ void TraceConfig::Clear() {
 | 
|    disabled_categories_.clear();
 | 
|    excluded_categories_.clear();
 | 
|    synthetic_delays_.clear();
 | 
| +  memory_dump_config_.clear();
 | 
|  }
 | 
|  
 | 
|  void TraceConfig::InitializeDefault() {
 | 
| @@ -279,14 +303,23 @@ void TraceConfig::InitializeFromConfigString(const std::string& config_string) {
 | 
|    else
 | 
|      enable_argument_filter_ = enable_argument_filter;
 | 
|  
 | 
| -
 | 
| -  base::ListValue* category_list = NULL;
 | 
| +  base::ListValue* category_list = nullptr;
 | 
|    if (dict->GetList(kIncludedCategoriesParam, &category_list))
 | 
|      SetCategoriesFromIncludedList(*category_list);
 | 
|    if (dict->GetList(kExcludedCategoriesParam, &category_list))
 | 
|      SetCategoriesFromExcludedList(*category_list);
 | 
|    if (dict->GetList(kSyntheticDelaysParam, &category_list))
 | 
|      SetSyntheticDelaysFromList(*category_list);
 | 
| +
 | 
| +  if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
 | 
| +    // If dump triggers not set, the client is using the legacy with just
 | 
| +    // category enabled. So, use the default periodic dump config.
 | 
| +    base::DictionaryValue* memory_dump_config = nullptr;
 | 
| +    if (dict->GetDictionary(kMemoryDumpConfigParam, &memory_dump_config))
 | 
| +      SetMemoryDumpConfig(*memory_dump_config);
 | 
| +    else
 | 
| +      SetDefaultMemoryDumpConfig();
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  void TraceConfig::InitializeFromStrings(
 | 
| @@ -353,6 +386,10 @@ void TraceConfig::InitializeFromStrings(
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| +
 | 
| +  if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
 | 
| +    SetDefaultMemoryDumpConfig();
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  void TraceConfig::SetCategoriesFromIncludedList(
 | 
| @@ -412,6 +449,48 @@ void TraceConfig::AddCategoryToDict(base::DictionaryValue& dict,
 | 
|    dict.Set(param, list.Pass());
 | 
|  }
 | 
|  
 | 
| +void TraceConfig::SetMemoryDumpConfig(
 | 
| +    const base::DictionaryValue& memory_dump_config) {
 | 
| +  memory_dump_config_.clear();
 | 
| +
 | 
| +  const base::ListValue* trigger_list = nullptr;
 | 
| +  if (!memory_dump_config.GetList(kTriggersParam, &trigger_list) ||
 | 
| +      trigger_list->GetSize() == 0) {
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  for (size_t i = 0; i < trigger_list->GetSize(); ++i) {
 | 
| +    const base::DictionaryValue* trigger = nullptr;
 | 
| +    if (!trigger_list->GetDictionary(i, &trigger))
 | 
| +      continue;
 | 
| +
 | 
| +    MemoryDumpTriggerConfig dump_config;
 | 
| +    std::string dump_type;
 | 
| +    int interval = 0;
 | 
| +
 | 
| +    if (!trigger->GetInteger(kPeriodicIntervalParam, &interval)) {
 | 
| +      continue;
 | 
| +    }
 | 
| +    DCHECK_GT(interval, 0);
 | 
| +    dump_config.periodic_interval_ms = static_cast<uint32>(interval);
 | 
| +    dump_config.level_of_detail = MemoryDumpArgs::LevelOfDetail::LOW;
 | 
| +
 | 
| +    if (trigger->GetString(kModeParam, &dump_type)) {
 | 
| +      if (dump_type == kDetailedParam) {
 | 
| +        dump_config.level_of_detail = MemoryDumpArgs::LevelOfDetail::HIGH;
 | 
| +      }
 | 
| +    }
 | 
| +
 | 
| +    memory_dump_config_.push_back(dump_config);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void TraceConfig::SetDefaultMemoryDumpConfig() {
 | 
| +  memory_dump_config_.clear();
 | 
| +  memory_dump_config_.push_back(kDefaultHeavyMemoryDumpTrigger);
 | 
| +  memory_dump_config_.push_back(kDefaultLightMemoryDumpTrigger);
 | 
| +}
 | 
| +
 | 
|  void TraceConfig::ToDict(base::DictionaryValue& dict) const {
 | 
|    switch (record_mode_) {
 | 
|      case RECORD_UNTIL_FULL:
 | 
| @@ -452,6 +531,35 @@ void TraceConfig::ToDict(base::DictionaryValue& dict) const {
 | 
|    AddCategoryToDict(dict, kIncludedCategoriesParam, categories);
 | 
|    AddCategoryToDict(dict, kExcludedCategoriesParam, excluded_categories_);
 | 
|    AddCategoryToDict(dict, kSyntheticDelaysParam, synthetic_delays_);
 | 
| +
 | 
| +  if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
 | 
| +    scoped_ptr<base::DictionaryValue> memory_dump_config(
 | 
| +        new base::DictionaryValue());
 | 
| +    scoped_ptr<base::ListValue> triggers_list(new base::ListValue());
 | 
| +    for (const MemoryDumpTriggerConfig& config : memory_dump_config_) {
 | 
| +      scoped_ptr<base::DictionaryValue> trigger_dict(
 | 
| +          new base::DictionaryValue());
 | 
| +      trigger_dict->SetInteger(kPeriodicIntervalParam,
 | 
| +                               static_cast<int>(config.periodic_interval_ms));
 | 
| +
 | 
| +      switch (config.level_of_detail) {
 | 
| +        case MemoryDumpArgs::LevelOfDetail::LOW:
 | 
| +          trigger_dict->SetString(kModeParam, kLightParam);
 | 
| +          break;
 | 
| +        case MemoryDumpArgs::LevelOfDetail::HIGH:
 | 
| +          trigger_dict->SetString(kModeParam, kDetailedParam);
 | 
| +          break;
 | 
| +        default:
 | 
| +          NOTREACHED();
 | 
| +      }
 | 
| +      triggers_list->Append(trigger_dict.Pass());
 | 
| +    }
 | 
| +
 | 
| +    // Empty triggers will still be specified explicitly since it means that
 | 
| +    // the periodic dumps are not enabled.
 | 
| +    memory_dump_config->Set(kTriggersParam, triggers_list.Pass());
 | 
| +    dict.Set(kMemoryDumpConfigParam, memory_dump_config.Pass());
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  std::string TraceConfig::ToTraceOptionsString() const {
 | 
| 
 |