| Index: components/metrics/profiler/tracking_synchronizer.cc
 | 
| diff --git a/components/metrics/profiler/tracking_synchronizer.cc b/components/metrics/profiler/tracking_synchronizer.cc
 | 
| index ad3644195f2a9236851b6aa1706f47b420d1ce92..ac91b3d5a91f49ebc10ccb660c3e1e16ba0473db 100644
 | 
| --- a/components/metrics/profiler/tracking_synchronizer.cc
 | 
| +++ b/components/metrics/profiler/tracking_synchronizer.cc
 | 
| @@ -180,11 +180,12 @@ base::LazyInstance
 | 
|  
 | 
|  // TrackingSynchronizer methods and members.
 | 
|  
 | 
| -TrackingSynchronizer::TrackingSynchronizer(base::TimeTicks now)
 | 
| -    : last_used_sequence_number_(kNeverUsableSequenceNumber), start_time_(now) {
 | 
| +TrackingSynchronizer::TrackingSynchronizer(scoped_ptr<base::TickClock> clock)
 | 
| +    : last_used_sequence_number_(kNeverUsableSequenceNumber),
 | 
| +      clock_(clock.Pass()) {
 | 
|    DCHECK(!g_tracking_synchronizer);
 | 
|    g_tracking_synchronizer = this;
 | 
| -  phase_start_times_.push_back(now);
 | 
| +  phase_start_times_.push_back(clock_->NowTicks());
 | 
|  
 | 
|  #if !defined(OS_IOS)
 | 
|    // TODO: This ifdef and other ifdefs for OS_IOS in this file are only
 | 
| @@ -227,6 +228,20 @@ void TrackingSynchronizer::FetchProfilerDataAsynchronously(
 | 
|        base::TimeDelta::FromMinutes(1));
 | 
|  }
 | 
|  
 | 
| +// static
 | 
| +void TrackingSynchronizer::OnProfilingPhaseCompleted(
 | 
| +    ProfilerEventProto::ProfilerEvent profiling_event) {
 | 
| +  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 | 
| +
 | 
| +  if (!g_tracking_synchronizer) {
 | 
| +    // System teardown is happening.
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  g_tracking_synchronizer->NotifyAllProcessesOfProfilingPhaseCompletion(
 | 
| +      profiling_event);
 | 
| +}
 | 
| +
 | 
|  void TrackingSynchronizer::OnPendingProcesses(int sequence_number,
 | 
|                                                int pending_processes,
 | 
|                                                bool end) {
 | 
| @@ -261,24 +276,63 @@ int TrackingSynchronizer::RegisterAndNotifyAllProcesses(
 | 
|    // Increment pending process count for sending browser's profiler data.
 | 
|    request->IncrementProcessesPending();
 | 
|  
 | 
| +  const int current_profiling_phase = phase_completion_events_sequence_.size();
 | 
| +
 | 
|  #if !defined(OS_IOS)
 | 
|    // Get profiler data from renderer and browser child processes.
 | 
| -  content::ProfilerController::GetInstance()->GetProfilerData(sequence_number);
 | 
| +  content::ProfilerController::GetInstance()->GetProfilerData(
 | 
| +      sequence_number, current_profiling_phase);
 | 
|  #endif
 | 
|  
 | 
|    // Send process data snapshot from browser process.
 | 
|    tracked_objects::ProcessDataSnapshot process_data_snapshot;
 | 
| -  tracked_objects::ThreadData::Snapshot(&process_data_snapshot);
 | 
| +  tracked_objects::ThreadData::Snapshot(current_profiling_phase,
 | 
| +                                        &process_data_snapshot);
 | 
| +
 | 
|    DecrementPendingProcessesAndSendData(sequence_number, process_data_snapshot,
 | 
|                                         content::PROCESS_TYPE_BROWSER);
 | 
|  
 | 
|    return sequence_number;
 | 
|  }
 | 
|  
 | 
| +void TrackingSynchronizer::RegisterPhaseCompletion(
 | 
| +    ProfilerEventProto::ProfilerEvent profiling_event) {
 | 
| +  phase_completion_events_sequence_.push_back(profiling_event);
 | 
| +  phase_start_times_.push_back(clock_->NowTicks());
 | 
| +}
 | 
| +
 | 
| +void TrackingSynchronizer::NotifyAllProcessesOfProfilingPhaseCompletion(
 | 
| +    ProfilerEventProto::ProfilerEvent profiling_event) {
 | 
| +  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 | 
| +
 | 
| +  if (variations::GetVariationParamValue("UMALogPhasedProfiling",
 | 
| +                                         "send_split_profiles") == "false") {
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  int profiling_phase = phase_completion_events_sequence_.size();
 | 
| +
 | 
| +  // If you hit this check, stop and think. You just added a new profiling
 | 
| +  // phase. Each profiling phase takes additional memory in DeathData's list of
 | 
| +  // snapshots. We cannot grow it indefinitely. Consider collapsing older phases
 | 
| +  // after they were sent to UMA server, or other ways to save memory.
 | 
| +  DCHECK_LT(profiling_phase, 1);
 | 
| +
 | 
| +  RegisterPhaseCompletion(profiling_event);
 | 
| +
 | 
| +#if !defined(OS_IOS)
 | 
| +  // Notify renderer and browser child processes.
 | 
| +  content::ProfilerController::GetInstance()->OnProfilingPhaseCompleted(
 | 
| +      profiling_phase);
 | 
| +#endif
 | 
| +
 | 
| +  // Notify browser process.
 | 
| +  tracked_objects::ThreadData::OnProfilingPhaseCompleted(profiling_phase);
 | 
| +}
 | 
| +
 | 
|  void TrackingSynchronizer::SendData(
 | 
|      const tracked_objects::ProcessDataSnapshot& profiler_data,
 | 
|      content::ProcessType process_type,
 | 
| -    base::TimeTicks now,
 | 
|      TrackingSynchronizerObserver* observer) const {
 | 
|    // We are going to loop though past profiling phases and notify the request
 | 
|    // about each phase that is contained in profiler_data. past_events
 | 
| @@ -290,20 +344,19 @@ void TrackingSynchronizer::SendData(
 | 
|    // comparison.
 | 
|    for (size_t phase = 0; phase <= phase_completion_events_sequence_.size();
 | 
|         ++phase) {
 | 
| -    auto it = profiler_data.phased_process_data_snapshots.find(phase);
 | 
| +    auto it = profiler_data.phased_snapshots.find(phase);
 | 
|  
 | 
| -    if (it != profiler_data.phased_process_data_snapshots.end()) {
 | 
| +    if (it != profiler_data.phased_snapshots.end()) {
 | 
|        // If the phase is contained in the received snapshot, notify the
 | 
|        // request.
 | 
| -      const base::TimeDelta phase_start =
 | 
| -          phase_start_times_[phase] - start_time_;
 | 
| -      const base::TimeDelta phase_finish =
 | 
| -          (phase + 1 < phase_start_times_.size() ? phase_start_times_[phase + 1]
 | 
| -                                                 : now) -
 | 
| -          start_time_;
 | 
| -      observer->ReceivedProfilerData(it->second, profiler_data.process_id,
 | 
| -                                     process_type, phase, phase_start,
 | 
| -                                     phase_finish, past_events);
 | 
| +      const base::TimeTicks phase_start = phase_start_times_[phase];
 | 
| +      const base::TimeTicks phase_finish = phase + 1 < phase_start_times_.size()
 | 
| +                                               ? phase_start_times_[phase + 1]
 | 
| +                                               : clock_->NowTicks();
 | 
| +      observer->ReceivedProfilerData(
 | 
| +          ProfilerDataAttributes(phase, profiler_data.process_id, process_type,
 | 
| +                                 phase_start, phase_finish),
 | 
| +          it->second, past_events);
 | 
|      }
 | 
|  
 | 
|      if (phase < phase_completion_events_sequence_.size()) {
 | 
| @@ -324,7 +377,7 @@ void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
 | 
|  
 | 
|    TrackingSynchronizerObserver* observer = request->callback_object_.get();
 | 
|    if (observer)
 | 
| -    SendData(profiler_data, process_type, base::TimeTicks::Now(), observer);
 | 
| +    SendData(profiler_data, process_type, observer);
 | 
|  
 | 
|    // Delete request if we have heard back from all child processes.
 | 
|    request->DecrementProcessesPending();
 | 
| 
 |