summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gypi3
-rw-r--r--base/metrics/histogram_flattener.h40
-rw-r--r--base/metrics/histogram_snapshot_manager.cc (renamed from chrome/common/metrics/histogram_sender.cc)43
-rw-r--r--base/metrics/histogram_snapshot_manager.h60
-rw-r--r--chrome/browser/browser_about_handler.cc1
-rw-r--r--chrome/browser/chrome_browser_main.cc7
-rw-r--r--chrome/browser/chrome_browser_main.h2
-rw-r--r--chrome/browser/metrics/histogram_synchronizer.cc264
-rw-r--r--chrome/browser/metrics/histogram_synchronizer.h180
-rw-r--r--chrome/browser/metrics/metrics_service.cc6
-rw-r--r--chrome/browser/metrics/tracking_synchronizer.cc13
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.cc9
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.h2
-rw-r--r--chrome/browser/ui/webui/about_ui.cc32
-rw-r--r--chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc1
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_common.gypi2
-rw-r--r--chrome/chrome_renderer.gypi2
-rw-r--r--chrome/common/chrome_constants.cc2
-rw-r--r--chrome/common/chrome_constants.h7
-rw-r--r--chrome/common/metrics/histogram_sender.h66
-rw-r--r--chrome/common/metrics/metrics_service_base.cc7
-rw-r--r--chrome/common/metrics/metrics_service_base.h22
-rw-r--r--chrome/common/render_messages.h4
-rw-r--r--chrome/common/url_constants.cc1
-rw-r--r--chrome/common/url_constants.h1
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc5
-rw-r--r--chrome/renderer/chrome_content_renderer_client.h2
-rw-r--r--chrome/renderer/page_load_histograms.cc15
-rw-r--r--chrome/renderer/page_load_histograms.h9
-rw-r--r--chrome/renderer/renderer_histogram_snapshots.cc92
-rw-r--r--chrome/renderer/renderer_histogram_snapshots.h58
-rw-r--r--content/browser/browser_child_process_host_impl.cc2
-rw-r--r--content/browser/histogram_controller.cc112
-rw-r--r--content/browser/histogram_controller.h70
-rw-r--r--content/browser/histogram_internals_request_job.cc72
-rw-r--r--content/browser/histogram_internals_request_job.h34
-rw-r--r--content/browser/histogram_message_filter.cc40
-rw-r--r--content/browser/histogram_message_filter.h42
-rw-r--r--content/browser/histogram_subscriber.h33
-rw-r--r--content/browser/histogram_synchronizer.cc346
-rw-r--r--content/browser/histogram_synchronizer.h151
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc2
-rw-r--r--content/browser/resource_context_impl.cc7
-rw-r--r--content/common/child_histogram_message_filter.cc98
-rw-r--r--content/common/child_histogram_message_filter.h65
-rw-r--r--content/common/child_process_messages.h18
-rw-r--r--content/common/child_thread.cc5
-rw-r--r--content/common/child_thread.h7
-rw-r--r--content/content_browser.gypi10
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/public/browser/histogram_fetcher.h29
-rw-r--r--content/public/common/content_constants.cc2
-rw-r--r--content/public/common/content_constants.h7
-rw-r--r--content/public/common/url_constants.cc1
-rw-r--r--content/public/common/url_constants.h1
-rw-r--r--content/public/renderer/render_thread.h2
-rw-r--r--content/public/test/mock_render_thread.h1
-rw-r--r--content/renderer/render_thread_impl.cc5
-rw-r--r--content/renderer/render_thread_impl.h1
-rw-r--r--content/test/mock_render_thread.cc3
61 files changed, 1330 insertions, 798 deletions
diff --git a/base/base.gypi b/base/base.gypi
index b605ae5..cfc904c 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -235,6 +235,9 @@
'message_pump_win.h',
'metrics/histogram.cc',
'metrics/histogram.h',
+ 'metrics/histogram_flattener.h',
+ 'metrics/histogram_snapshot_manager.cc',
+ 'metrics/histogram_snapshot_manager.h',
'metrics/stats_counters.cc',
'metrics/stats_counters.h',
'metrics/stats_table.cc',
diff --git a/base/metrics/histogram_flattener.h b/base/metrics/histogram_flattener.h
new file mode 100644
index 0000000..edb1511
--- /dev/null
+++ b/base/metrics/histogram_flattener.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef BASE_METRICS_HISTOGRAM_FLATTENER_H_
+#define BASE_METRICS_HISTOGRAM_FLATTENER_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram.h"
+
+namespace base {
+
+// HistogramFlattener is an interface for the logistics of gathering up
+// available histograms for recording. The implementors handle the exact lower
+// level recording mechanism, or error report mechanism.
+class BASE_EXPORT HistogramFlattener {
+ public:
+ virtual void RecordDelta(const base::Histogram& histogram,
+ const base::Histogram::SampleSet& snapshot) = 0;
+
+ // Record various errors found during attempts to record histograms.
+ virtual void InconsistencyDetected(int problem) = 0;
+ virtual void UniqueInconsistencyDetected(int problem) = 0;
+ virtual void SnapshotProblemResolved(int amount) = 0;
+
+ protected:
+ HistogramFlattener() {}
+ virtual ~HistogramFlattener() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HistogramFlattener);
+};
+
+} // namespace base
+
+#endif // BASE_METRICS_HISTOGRAM_FLATTENER_H_
diff --git a/chrome/common/metrics/histogram_sender.cc b/base/metrics/histogram_snapshot_manager.cc
index dfb513a..b325f73 100644
--- a/chrome/common/metrics/histogram_sender.cc
+++ b/base/metrics/histogram_snapshot_manager.cc
@@ -2,31 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/common/metrics/histogram_sender.h"
+#include "base/metrics/histogram_snapshot_manager.h"
using base::Histogram;
using base::StatisticsRecorder;
-HistogramSender::HistogramSender() {}
+namespace base {
-HistogramSender::~HistogramSender() {}
+HistogramSnapshotManager::HistogramSnapshotManager(
+ HistogramFlattener* histogram_flattener)
+ : histogram_flattener_(histogram_flattener) {
+ DCHECK(histogram_flattener_);
+}
+
+HistogramSnapshotManager::~HistogramSnapshotManager() {}
-void HistogramSender::TransmitAllHistograms(Histogram::Flags flag_to_set,
- bool send_only_uma) {
+void HistogramSnapshotManager::PrepareDeltas(Histogram::Flags flag_to_set,
+ bool record_only_uma) {
StatisticsRecorder::Histograms histograms;
StatisticsRecorder::GetHistograms(&histograms);
for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin();
histograms.end() != it;
++it) {
(*it)->SetFlags(flag_to_set);
- if (send_only_uma &&
+ if (record_only_uma &&
0 == ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag))
continue;
- TransmitHistogram(**it);
+ PrepareDelta(**it);
}
}
-void HistogramSender::TransmitHistogram(const Histogram& histogram) {
+void HistogramSnapshotManager::PrepareDelta(const Histogram& histogram) {
+ DCHECK(histogram_flattener_);
+
// Get up-to-date snapshot of sample stats.
Histogram::SampleSet snapshot;
histogram.SnapshotSample(&snapshot);
@@ -47,20 +55,20 @@ void HistogramSender::TransmitHistogram(const Histogram& histogram) {
if (corruption) {
NOTREACHED();
- InconsistencyDetected(corruption);
- // Don't send corrupt data to metrics survices.
+ histogram_flattener_->InconsistencyDetected(corruption);
+ // Don't record corrupt data to metrics survices.
if (NULL == inconsistencies_.get())
inconsistencies_.reset(new ProblemMap);
int old_corruption = (*inconsistencies_)[histogram_name];
if (old_corruption == (corruption | old_corruption))
return; // We've already seen this corruption for this histogram.
(*inconsistencies_)[histogram_name] |= corruption;
- UniqueInconsistencyDetected(corruption);
+ histogram_flattener_->UniqueInconsistencyDetected(corruption);
return;
}
- // Find the already sent stats, or create an empty set. Remove from our
- // snapshot anything that we've already sent.
+ // Find the already recorded stats, or create an empty set. Remove from our
+ // snapshot anything that we've already recorded.
LoggedSampleMap::iterator it = logged_samples_.find(histogram_name);
Histogram::SampleSet* already_logged;
if (logged_samples_.end() == it) {
@@ -70,14 +78,14 @@ void HistogramSender::TransmitHistogram(const Histogram& histogram) {
} else {
already_logged = &(it->second);
int64 discrepancy(already_logged->TotalCount() -
- already_logged->redundant_count());
+ already_logged->redundant_count());
if (discrepancy) {
NOTREACHED(); // Already_logged has become corrupt.
int problem = static_cast<int>(discrepancy);
if (problem != discrepancy)
problem = INT_MAX;
- SnapshotProblemResolved(problem);
- // With no valid baseline, we'll act like we've sent everything in our
+ histogram_flattener_->SnapshotProblemResolved(problem);
+ // With no valid baseline, we'll act like we've recorded everything in our
// snapshot.
already_logged->Subtract(*already_logged);
already_logged->Add(snapshot);
@@ -88,8 +96,9 @@ void HistogramSender::TransmitHistogram(const Histogram& histogram) {
// Snapshot now contains only a delta to what we've already_logged.
if (snapshot.redundant_count() > 0) {
- TransmitHistogramDelta(histogram, snapshot);
+ histogram_flattener_->RecordDelta(histogram, snapshot);
// Add new data into our running total.
already_logged->Add(snapshot);
}
}
+} // namespace base
diff --git a/base/metrics/histogram_snapshot_manager.h b/base/metrics/histogram_snapshot_manager.h
new file mode 100644
index 0000000..a945ac7
--- /dev/null
+++ b/base/metrics/histogram_snapshot_manager.h
@@ -0,0 +1,60 @@
+// 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.
+
+#ifndef BASE_METRICS_HISTOGRAM_SNAPSHOT_MANAGER_H_
+#define BASE_METRICS_HISTOGRAM_SNAPSHOT_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_flattener.h"
+
+namespace base {
+
+// HistogramSnapshotManager handles the logistics of gathering up available
+// histograms for recording either to disk or for transmission (such as from
+// renderer to browser, or from browser to UMA upload). Since histograms can sit
+// in memory for an extended period of time, and are vulnerable to memory
+// corruption, this class also validates as much rendundancy as it can before
+// calling for the marginal change (a.k.a., delta) in a histogram to be
+// recorded.
+class BASE_EXPORT HistogramSnapshotManager {
+ public:
+ explicit HistogramSnapshotManager(HistogramFlattener* histogram_flattener);
+ virtual ~HistogramSnapshotManager();
+
+ // Snapshot all histograms, and ask |histogram_flattener_| to record the
+ // delta. The arguments allow selecting only a subset of histograms for
+ // recording, or to set a flag in each recorded histogram.
+ void PrepareDeltas(base::Histogram::Flags flags_to_set, bool record_only_uma);
+
+ private:
+ // Maintain a map of histogram names to the sample stats we've recorded.
+ typedef std::map<std::string, base::Histogram::SampleSet> LoggedSampleMap;
+ // List of histograms names, and their encontered corruptions.
+ typedef std::map<std::string, int> ProblemMap;
+
+ // Snapshot this histogram, and record the delta.
+ void PrepareDelta(const base::Histogram& histogram);
+
+ // For histograms, track what we've already recorded (as a sample for
+ // each histogram) so that we can record only the delta with the next log.
+ LoggedSampleMap logged_samples_;
+
+ // List of histograms found corrupt to be corrupt, and their problems.
+ scoped_ptr<ProblemMap> inconsistencies_;
+
+ // |histogram_flattener_| handles the logistics of recording the histogram
+ // deltas.
+ HistogramFlattener* histogram_flattener_; // Weak.
+
+ DISALLOW_COPY_AND_ASSIGN(HistogramSnapshotManager);
+};
+
+} // namespace base
+
+#endif // BASE_METRICS_HISTOGRAM_SNAPSHOT_MANAGER_H_
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc
index e371c06..40d5bae 100644
--- a/chrome/browser/browser_about_handler.cc
+++ b/chrome/browser/browser_about_handler.cc
@@ -33,7 +33,6 @@ const char* const kChromePaths[] = {
chrome::kChromeUIFlagsHost,
chrome::kChromeUIFlashHost,
chrome::kChromeUIGpuInternalsHost,
- chrome::kChromeUIHistogramsHost,
chrome::kChromeUIHistoryHost,
chrome::kChromeUIIPCHost,
chrome::kChromeUIInspectHost,
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 37fb0c0..c984994 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -52,7 +52,6 @@
#include "chrome/browser/language_usage_metrics.h"
#include "chrome/browser/managed_mode.h"
#include "chrome/browser/metrics/field_trial_synchronizer.h"
-#include "chrome/browser/metrics/histogram_synchronizer.h"
#include "chrome/browser/metrics/metrics_log.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/metrics/thread_watcher.h"
@@ -1402,11 +1401,7 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
InitializeNetworkOptions(parsed_command_line());
- // Initialize histogram synchronizer system. This is a singleton and is used
- // for posting tasks via base::Bind. Its deleted when it goes out of scope.
- // Even though base::Bind does AddRef and Release, the object will not
- // be deleted after the Task is executed.
- histogram_synchronizer_ = new HistogramSynchronizer();
+ // Initialize tracking synchronizer system.
tracking_synchronizer_ = new chrome_browser_metrics::TrackingSynchronizer();
// Now that all preferences have been registered, set the install date
diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h
index ab96517..00c05d0 100644
--- a/chrome/browser/chrome_browser_main.h
+++ b/chrome/browser/chrome_browser_main.h
@@ -21,7 +21,6 @@
class BrowserProcessImpl;
class ChromeBrowserMainExtraParts;
class FieldTrialSynchronizer;
-class HistogramSynchronizer;
class MetricsService;
class PrefService;
class Profile;
@@ -195,7 +194,6 @@ class ChromeBrowserMainParts : public content::BrowserMainParts {
scoped_ptr<StartupBrowserCreator> browser_creator_;
scoped_ptr<BrowserProcessImpl> browser_process_;
- scoped_refptr<HistogramSynchronizer> histogram_synchronizer_;
scoped_refptr<chrome_browser_metrics::TrackingSynchronizer>
tracking_synchronizer_;
scoped_ptr<ProcessSingleton> process_singleton_;
diff --git a/chrome/browser/metrics/histogram_synchronizer.cc b/chrome/browser/metrics/histogram_synchronizer.cc
deleted file mode 100644
index a5e2047..0000000
--- a/chrome/browser/metrics/histogram_synchronizer.cc
+++ /dev/null
@@ -1,264 +0,0 @@
-// 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.
-
-#include "chrome/browser/metrics/histogram_synchronizer.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/render_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-
-using base::Time;
-using base::TimeDelta;
-using base::TimeTicks;
-using content::BrowserThread;
-
-// Negative numbers are never used as sequence numbers. We explicitly pick a
-// negative number that is "so negative" that even when we add one (as is done
-// when we generated the next sequence number) that it will still be negative.
-// We have code that handles wrapping around on an overflow into negative
-// territory.
-static const int kNeverUsableSequenceNumber = -2;
-
-HistogramSynchronizer::HistogramSynchronizer()
- : lock_(),
- received_all_renderer_histograms_(&lock_),
- callback_thread_(NULL),
- last_used_sequence_number_(kNeverUsableSequenceNumber),
- async_sequence_number_(kNeverUsableSequenceNumber),
- async_renderers_pending_(0),
- synchronous_sequence_number_(kNeverUsableSequenceNumber),
- synchronous_renderers_pending_(0) {
- DCHECK(histogram_synchronizer_ == NULL);
- histogram_synchronizer_ = this;
-}
-
-HistogramSynchronizer::~HistogramSynchronizer() {
- // Just in case we have any pending tasks, clear them out.
- SetCallbackTaskAndThread(NULL, base::Closure());
- histogram_synchronizer_ = NULL;
-}
-
-// static
-HistogramSynchronizer* HistogramSynchronizer::CurrentSynchronizer() {
- DCHECK(histogram_synchronizer_ != NULL);
- return histogram_synchronizer_;
-}
-
-void HistogramSynchronizer::FetchRendererHistogramsSynchronously(
- TimeDelta wait_time) {
- NotifyAllRenderers(SYNCHRONOUS_HISTOGRAMS);
-
- TimeTicks start = TimeTicks::Now();
- TimeTicks end_time = start + wait_time;
- int unresponsive_renderer_count;
- {
- base::AutoLock auto_lock(lock_);
- while (synchronous_renderers_pending_ > 0 && TimeTicks::Now() < end_time) {
- wait_time = end_time - TimeTicks::Now();
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- received_all_renderer_histograms_.TimedWait(wait_time);
- }
- unresponsive_renderer_count = synchronous_renderers_pending_;
- synchronous_renderers_pending_ = 0;
- synchronous_sequence_number_ = kNeverUsableSequenceNumber;
- }
- UMA_HISTOGRAM_COUNTS("Histogram.RendersNotRespondingSynchronous",
- unresponsive_renderer_count);
- if (!unresponsive_renderer_count)
- UMA_HISTOGRAM_TIMES("Histogram.FetchRendererHistogramsSynchronously",
- TimeTicks::Now() - start);
-}
-
-// static
-void HistogramSynchronizer::FetchRendererHistogramsAsynchronously(
- MessageLoop* callback_thread,
- const base::Closure& callback,
- base::TimeDelta wait_time) {
- DCHECK(callback_thread != NULL);
- DCHECK(!callback.is_null());
-
- HistogramSynchronizer* current_synchronizer = CurrentSynchronizer();
-
- if (current_synchronizer == NULL) {
- // System teardown is happening.
- callback_thread->PostTask(FROM_HERE, callback);
- return;
- }
-
- current_synchronizer->SetCallbackTaskAndThread(callback_thread,
- callback);
-
- int sequence_number =
- current_synchronizer->NotifyAllRenderers(ASYNC_HISTOGRAMS);
-
- // Post a task that would be called after waiting for wait_time. This acts
- // as a watchdog, to ensure that a non-responsive renderer won't block us from
- // making the callback.
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback,
- current_synchronizer,
- sequence_number),
- wait_time);
-}
-
-// static
-void HistogramSynchronizer::DeserializeHistogramList(
- int sequence_number,
- const std::vector<std::string>& histograms) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- for (std::vector<std::string>::const_iterator it = histograms.begin();
- it < histograms.end();
- ++it) {
- base::Histogram::DeserializeHistogramInfo(*it);
- }
-
- HistogramSynchronizer* current_synchronizer = CurrentSynchronizer();
- if (current_synchronizer == NULL)
- return;
-
- // Record that we have received a histogram from renderer process.
- current_synchronizer->DecrementPendingRenderers(sequence_number);
-}
-
-int HistogramSynchronizer::NotifyAllRenderers(
- RendererHistogramRequester requester) {
- // To iterate over RenderProcessHosts, or to send messages to the hosts, we
- // need to be on the UI thread.
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- int notification_count = 0;
- for (content::RenderProcessHost::iterator it(
- content::RenderProcessHost::AllHostsIterator());
- !it.IsAtEnd(); it.Advance())
- ++notification_count;
-
- int sequence_number = GetNextAvailableSequenceNumber(requester,
- notification_count);
- for (content::RenderProcessHost::iterator it(
- content::RenderProcessHost::AllHostsIterator());
- !it.IsAtEnd(); it.Advance()) {
- if (!it.GetCurrentValue()->Send(
- new ChromeViewMsg_GetRendererHistograms(sequence_number)))
- DecrementPendingRenderers(sequence_number);
- }
-
- return sequence_number;
-}
-
-void HistogramSynchronizer::DecrementPendingRenderers(int sequence_number) {
- bool synchronous_completed = false;
- bool asynchronous_completed = false;
-
- {
- base::AutoLock auto_lock(lock_);
- if (sequence_number == async_sequence_number_) {
- if (--async_renderers_pending_ <= 0)
- asynchronous_completed = true;
- } else if (sequence_number == synchronous_sequence_number_) {
- if (--synchronous_renderers_pending_ <= 0)
- synchronous_completed = true;
- }
- }
-
- if (asynchronous_completed)
- ForceHistogramSynchronizationDoneCallback(sequence_number);
- else if (synchronous_completed)
- received_all_renderer_histograms_.Signal();
-}
-
-void HistogramSynchronizer::SetCallbackTaskAndThread(
- MessageLoop* callback_thread,
- const base::Closure& callback) {
- base::Closure old_callback;
- MessageLoop* old_thread = NULL;
- TimeTicks old_start_time;
- int unresponsive_renderers;
- const TimeTicks now = TimeTicks::Now();
- {
- base::AutoLock auto_lock(lock_);
- old_callback = callback_;
- callback_ = callback;
- old_thread = callback_thread_;
- callback_thread_ = callback_thread;
- unresponsive_renderers = async_renderers_pending_;
- old_start_time = async_callback_start_time_;
- async_callback_start_time_ = now;
- // Prevent premature calling of our new callbacks.
- async_sequence_number_ = kNeverUsableSequenceNumber;
- }
- // Just in case there was a task pending....
- InternalPostTask(old_thread, old_callback, unresponsive_renderers,
- old_start_time);
-}
-
-void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback(
- int sequence_number) {
- base::Closure callback;
- MessageLoop* thread = NULL;
- TimeTicks started;
- int unresponsive_renderers;
- {
- base::AutoLock lock(lock_);
- if (sequence_number != async_sequence_number_)
- return;
- callback = callback_;
- thread = callback_thread_;
- callback_.Reset();
- callback_thread_ = NULL;
- started = async_callback_start_time_;
- unresponsive_renderers = async_renderers_pending_;
- }
- InternalPostTask(thread, callback, unresponsive_renderers, started);
-}
-
-void HistogramSynchronizer::InternalPostTask(MessageLoop* thread,
- const base::Closure& callback,
- int unresponsive_renderers,
- const base::TimeTicks& started) {
- if (callback.is_null() || !thread)
- return;
- UMA_HISTOGRAM_COUNTS("Histogram.RendersNotRespondingAsynchronous",
- unresponsive_renderers);
- if (!unresponsive_renderers) {
- UMA_HISTOGRAM_TIMES("Histogram.FetchRendererHistogramsAsynchronously",
- TimeTicks::Now() - started);
- }
-
- thread->PostTask(FROM_HERE, callback);
-}
-
-int HistogramSynchronizer::GetNextAvailableSequenceNumber(
- RendererHistogramRequester requester,
- int renderer_count) {
- base::AutoLock auto_lock(lock_);
- ++last_used_sequence_number_;
- // Watch out for wrapping to a negative number.
- if (last_used_sequence_number_ < 0) {
- // Bypass the reserved number, which is used when a renderer spontaneously
- // decides to send some histogram data.
- last_used_sequence_number_ =
- chrome::kHistogramSynchronizerReservedSequenceNumber + 1;
- }
- DCHECK_NE(last_used_sequence_number_,
- chrome::kHistogramSynchronizerReservedSequenceNumber);
- if (requester == ASYNC_HISTOGRAMS) {
- async_sequence_number_ = last_used_sequence_number_;
- async_renderers_pending_ = renderer_count;
- } else if (requester == SYNCHRONOUS_HISTOGRAMS) {
- synchronous_sequence_number_ = last_used_sequence_number_;
- synchronous_renderers_pending_ = renderer_count;
- }
- return last_used_sequence_number_;
-}
-
-// static
-HistogramSynchronizer* HistogramSynchronizer::histogram_synchronizer_ = NULL;
diff --git a/chrome/browser/metrics/histogram_synchronizer.h b/chrome/browser/metrics/histogram_synchronizer.h
deleted file mode 100644
index 8bcf641..0000000
--- a/chrome/browser/metrics/histogram_synchronizer.h
+++ /dev/null
@@ -1,180 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_METRICS_HISTOGRAM_SYNCHRONIZER_H_
-#define CHROME_BROWSER_METRICS_HISTOGRAM_SYNCHRONIZER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/time.h"
-
-class MessageLoop;
-
-// This class maintains state that is used to upload histogram data from the
-// various renderer processes, into the browser process. Such transactions are
-// usually instigated by the browser. In general, a renderer process will
-// respond by gathering snapshots of all internal histograms, calculating what
-// has changed since its last upload, and transmitting a pickled collection of
-// deltas.
-//
-// There are actually two modes of update request. One is synchronous (and
-// blocks the UI thread, waiting to populate an about:histograms tab) and the
-// other is asynchronous, and used by the metrics services in preparation for a
-// log upload.
-//
-// To assure that all the renderers have responded, a counter is maintained (for
-// each mode) to indicate the number of pending (not yet responsive) renderers.
-// To avoid confusion about a response (i.e., is the renderer responding to a
-// current request for an update, or to an old request for an update) we tag
-// each group of requests with a sequence number. When an update arrives we can
-// ignore it (relative to the counter) if it does not relate to a current
-// outstanding sequence number.
-//
-// There is one final mode of use, where a renderer spontaneously decides to
-// transmit a collection of histogram data. This is designed for use when the
-// renderer is terminating. Unfortunately, renders may be terminated without
-// warning, and the best we can do is periodically acquire data from a tab, such
-// as when a page load has completed. In this mode, the renderer uses a
-// reserved sequence number, different from any sequence number that might be
-// specified by a browser request. Since this sequence number can't match an
-// outstanding sequence number, the pickled data is accepted into the browser,
-// but there is no impact on the counters.
-
-class HistogramSynchronizer : public
- base::RefCountedThreadSafe<HistogramSynchronizer> {
- public:
-
- enum RendererHistogramRequester {
- ASYNC_HISTOGRAMS,
- SYNCHRONOUS_HISTOGRAMS
- };
-
- // Construction also sets up the global singleton instance. This instance is
- // used to communicate between the IO and UI thread, and is destroyed only
- // as the main thread (browser_main) terminates, which means the IO thread has
- // already completed, and will not need this instance any further.
- HistogramSynchronizer();
-
- // Return pointer to the singleton instance, which is allocated and
- // deallocated on the main UI thread (during system startup and teardown).
- static HistogramSynchronizer* CurrentSynchronizer();
-
- // Contact all renderers, and get them to upload to the browser any/all
- // changes to histograms. Return when all changes have been acquired, or when
- // the wait time expires (whichever is sooner). This method is called on the
- // main UI thread from about:histograms.
- void FetchRendererHistogramsSynchronously(base::TimeDelta wait_time);
-
- // Contact all renderers, and get them to upload to the browser any/all
- // changes to histograms. When all changes have been acquired, or when the
- // wait time expires (whichever is sooner), post the callback to the
- // specified message loop. Note the callback is posted exactly once.
- static void FetchRendererHistogramsAsynchronously(
- MessageLoop* callback_thread,
- const base::Closure& callback,
- base::TimeDelta wait_time);
-
- // This method is called on the IO thread. Deserializes the histograms and
- // records that we have received histograms from a renderer process.
- static void DeserializeHistogramList(
- int sequence_number, const std::vector<std::string>& histograms);
-
- private:
- friend class base::RefCountedThreadSafe<HistogramSynchronizer>;
-
- ~HistogramSynchronizer();
-
- // Establish a new sequence_number_, and use it to notify all the renderers of
- // the need to supply, to the browser, any changes in their histograms.
- // The argument indicates whether this will set async_sequence_number_ or
- // synchronous_sequence_number_.
- // Return the sequence number that was used.
- int NotifyAllRenderers(RendererHistogramRequester requester);
-
- // Records that we are waiting for one less histogram from a renderer for the
- // given sequence number. If we have received a response from all renderers,
- // either signal the waiting process or call the callback function.
- void DecrementPendingRenderers(int sequence_number);
-
- // Set the callback_thread_ and callback_ members. If these members already
- // had values, then as a side effect, post the old callback_ to the old
- // callaback_thread_. This side effect should not generally happen, but is in
- // place to assure correctness (that any tasks that were set, are eventually
- // called, and never merely discarded).
- void SetCallbackTaskAndThread(MessageLoop* callback_thread,
- const base::Closure& callback);
-
- void ForceHistogramSynchronizationDoneCallback(int sequence_number);
-
- // Gets a new sequence number to be sent to renderers from browser process and
- // set the number of pending responses for the given type to renderer_count.
- int GetNextAvailableSequenceNumber(RendererHistogramRequester requster,
- int renderer_count);
-
- // Internal helper function, to post task, and record callback stats.
- void InternalPostTask(MessageLoop* thread,
- const base::Closure& callback,
- int unresponsive_renderers,
- const base::TimeTicks& started);
-
- // This lock_ protects access to all members.
- base::Lock lock_;
-
- // This condition variable is used to block caller of the synchronous request
- // to update histograms, and to signal that thread when updates are completed.
- base::ConditionVariable received_all_renderer_histograms_;
-
- // When a request is made to asynchronously update the histograms, we store
- // the task and thread we use to post a completion notification in
- // callback_ and callback_thread_.
- base::Closure callback_;
- MessageLoop* callback_thread_;
-
- // We don't track the actual renderers that are contacted for an update, only
- // the count of the number of renderers, and we can sometimes time-out and
- // give up on a "slow to respond" renderer. We use a sequence_number to be
- // sure a response from a renderer is associated with the current round of
- // requests (and not merely a VERY belated prior response).
- // All sequence numbers used are non-negative.
- // last_used_sequence_number_ is the most recently used number (used to avoid
- // reuse for a long time).
- int last_used_sequence_number_;
-
- // The sequence number used by the most recent asynchronous update request to
- // contact all renderers.
- int async_sequence_number_;
-
- // The number of renderers that have not yet responded to requests (as part of
- // an asynchronous update).
- int async_renderers_pending_;
-
- // The time when we were told to start the fetch histograms asynchronously
- // from renderers.
- base::TimeTicks async_callback_start_time_;
-
- // The sequence number used by the most recent synchronous update request to
- // contact all renderers.
- int synchronous_sequence_number_;
-
- // The number of renderers that have not yet responded to requests (as part of
- // a synchronous update).
- int synchronous_renderers_pending_;
-
- // This singleton instance should be started during the single threaded
- // portion of main(). It initializes globals to provide support for all future
- // calls. This object is created on the UI thread, and it is destroyed after
- // all the other threads have gone away. As a result, it is ok to call it
- // from the UI thread (for UMA uploads), or for about:histograms.
- static HistogramSynchronizer* histogram_synchronizer_;
-
- DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer);
-};
-
-#endif // CHROME_BROWSER_METRICS_HISTOGRAM_SYNCHRONIZER_H_
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 985e512..d2e5a84 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -167,7 +167,6 @@
#include "chrome/browser/extensions/process_map.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/memory_details.h"
-#include "chrome/browser/metrics/histogram_synchronizer.h"
#include "chrome/browser/metrics/metrics_log.h"
#include "chrome/browser/metrics/metrics_log_serializer.h"
#include "chrome/browser/metrics/metrics_reporting_scheduler.h"
@@ -188,6 +187,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/histogram_fetcher.h"
#include "content/public/browser/load_notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
@@ -1210,9 +1210,9 @@ void MetricsService::OnMemoryDetailCollectionDone() {
base::StatisticsRecorder::CollectHistogramStats("Browser");
// Set up the callback to task to call after we receive histograms from all
- // renderer processes. Wait time specifies how long to wait before absolutely
+ // child processes. Wait time specifies how long to wait before absolutely
// calling us back on the task.
- HistogramSynchronizer::FetchRendererHistogramsAsynchronously(
+ content::FetchHistogramsAsynchronously(
MessageLoop::current(), callback,
base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration));
}
diff --git a/chrome/browser/metrics/tracking_synchronizer.cc b/chrome/browser/metrics/tracking_synchronizer.cc
index dbfaea0..75d7c0e 100644
--- a/chrome/browser/metrics/tracking_synchronizer.cc
+++ b/chrome/browser/metrics/tracking_synchronizer.cc
@@ -86,7 +86,6 @@ class TrackingSynchronizer::RequestContext {
RequestContext::Unregister(sequence_number_);
}
-
// Register |callback_object| in |outstanding_requests_| map for the given
// |sequence_number|.
static RequestContext* Register(
@@ -116,7 +115,7 @@ class TrackingSynchronizer::RequestContext {
return request;
}
- // Delete the entry for the given sequence_number| from
+ // Delete the entry for the given |sequence_number| from
// |outstanding_requests_| map. This method is called when all changes have
// been acquired, or when the wait time expires (whichever is sooner).
static void Unregister(int sequence_number) {
@@ -144,7 +143,6 @@ class TrackingSynchronizer::RequestContext {
unresponsive_processes);
}
-
// Delete all the entries in |outstanding_requests_| map.
static void OnShutdown() {
// Just in case we have any pending tasks, clear them out.
@@ -171,13 +169,14 @@ class TrackingSynchronizer::RequestContext {
// Map of all outstanding RequestContexts, from sequence_number_ to
// RequestContext.
- static base::LazyInstance<RequestContextMap> outstanding_requests_;
+ static base::LazyInstance<RequestContextMap>::Leaky outstanding_requests_;
};
// static
-base::LazyInstance<TrackingSynchronizer::RequestContext::RequestContextMap>
- TrackingSynchronizer::RequestContext::outstanding_requests_ =
- LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance
+ <TrackingSynchronizer::RequestContext::RequestContextMap>::Leaky
+ TrackingSynchronizer::RequestContext::outstanding_requests_ =
+ LAZY_INSTANCE_INITIALIZER;
// TrackingSynchronizer methods and members.
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index 6ca69d6..321825c 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -19,7 +19,6 @@
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/metrics/histogram_synchronizer.h"
#include "chrome/browser/nacl_host/nacl_process_host.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/predictor.h"
@@ -76,8 +75,6 @@ bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_LaunchNaCl, OnLaunchNaCl)
#endif
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DnsPrefetch, OnDnsPrefetch)
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RendererHistograms,
- OnRendererHistograms)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ResourceTypeStats,
OnResourceTypeStats)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_UpdatedCacheStats,
@@ -180,12 +177,6 @@ void ChromeRenderMessageFilter::OnDnsPrefetch(
profile_->GetNetworkPredictor()->DnsPrefetchList(hostnames);
}
-void ChromeRenderMessageFilter::OnRendererHistograms(
- int sequence_number,
- const std::vector<std::string>& histograms) {
- HistogramSynchronizer::DeserializeHistogramList(sequence_number, histograms);
-}
-
void ChromeRenderMessageFilter::OnResourceTypeStats(
const WebCache::ResourceTypeStats& stats) {
HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB",
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h
index 9440848..71898ad 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.h
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.h
@@ -78,8 +78,6 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter {
IPC::Message* reply_msg);
#endif
void OnDnsPrefetch(const std::vector<std::string>& hostnames);
- void OnRendererHistograms(int sequence_number,
- const std::vector<std::string>& histogram_info);
void OnResourceTypeStats(const WebKit::WebCache::ResourceTypeStats& stats);
void OnUpdatedCacheStats(const WebKit::WebCache::UsageStats& stats);
void OnFPS(int routing_id, float fps);
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index 856aca4..e441804 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -18,7 +18,6 @@
#include "base/json/json_writer.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/singleton.h"
-#include "base/metrics/histogram.h"
#include "base/metrics/stats_table.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
@@ -33,7 +32,6 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/memory_details.h"
-#include "chrome/browser/metrics/histogram_synchronizer.h"
#include "chrome/browser/net/predictor.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/plugin_prefs.h"
@@ -800,34 +798,6 @@ class AboutDnsHandler : public base::RefCountedThreadSafe<AboutDnsHandler> {
DISALLOW_COPY_AND_ASSIGN(AboutDnsHandler);
};
-std::string AboutHistograms(const std::string& query) {
- TimeDelta wait_time = TimeDelta::FromMilliseconds(10000);
-
-#ifndef NDEBUG
- base::StatisticsRecorder::CollectHistogramStats("Browser");
-#endif
-
- HistogramSynchronizer* current_synchronizer =
- HistogramSynchronizer::CurrentSynchronizer();
- DCHECK(current_synchronizer != NULL);
- current_synchronizer->FetchRendererHistogramsSynchronously(wait_time);
-
- std::string unescaped_query;
- std::string unescaped_title("About Histograms");
- if (!query.empty()) {
- unescaped_query = net::UnescapeURLComponent(query,
- net::UnescapeRule::NORMAL);
- unescaped_title += " - " + unescaped_query;
- }
-
- std::string data;
- AppendHeader(&data, 0, unescaped_title);
- AppendBody(&data);
- base::StatisticsRecorder::WriteHTMLGraph(unescaped_query, &data);
- AppendFooter(&data);
- return data;
-}
-
void FinishMemoryDataRequest(const std::string& path,
AboutUIHTMLSource* source,
int request_id) {
@@ -1406,8 +1376,6 @@ void AboutUIHTMLSource::StartDataRequest(const std::string& path,
} else if (host == chrome::kChromeUIDNSHost) {
AboutDnsHandler::Start(this, request_id);
return;
- } else if (host == chrome::kChromeUIHistogramsHost) {
- response = AboutHistograms(path);
#if defined(OS_LINUX) || defined(OS_OPENBSD)
} else if (host == chrome::kChromeUILinuxProxyConfigHost) {
response = AboutLinuxProxyConfig();
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 2d4aef0..3876837 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -329,7 +329,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
if (url.host() == chrome::kChromeUIChromeURLsHost ||
url.host() == chrome::kChromeUICreditsHost ||
url.host() == chrome::kChromeUIDNSHost ||
- url.host() == chrome::kChromeUIHistogramsHost ||
url.host() == chrome::kChromeUIMemoryHost ||
url.host() == chrome::kChromeUIMemoryRedirectHost ||
url.host() == chrome::kChromeUIStatsHost ||
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 4e275aa..c350214 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1410,8 +1410,6 @@
'browser/memory_purger.h',
'browser/metrics/field_trial_synchronizer.cc',
'browser/metrics/field_trial_synchronizer.h',
- 'browser/metrics/histogram_synchronizer.cc',
- 'browser/metrics/histogram_synchronizer.h',
'browser/metrics/metric_event_duration_details.h',
'browser/metrics/metrics_log.cc',
'browser/metrics/metrics_log.h',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 06c2130..ea8fad6 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -223,8 +223,6 @@
'common/mac/objc_zombie.mm',
'common/metrics/experiments_helper.cc',
'common/metrics/experiments_helper.h',
- 'common/metrics/histogram_sender.cc',
- 'common/metrics/histogram_sender.h',
'common/metrics/metrics_log_base.cc',
'common/metrics/metrics_log_base.h',
'common/metrics/metrics_log_manager.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index e26075d..0236adf6 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -227,8 +227,6 @@
'renderer/print_web_view_helper_linux.cc',
'renderer/print_web_view_helper_mac.mm',
'renderer/print_web_view_helper_win.cc',
- 'renderer/renderer_histogram_snapshots.cc',
- 'renderer/renderer_histogram_snapshots.h',
'renderer/safe_browsing/feature_extractor_clock.cc',
'renderer/safe_browsing/feature_extractor_clock.h',
'renderer/safe_browsing/features.cc',
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index c089a98..1d4a4e5 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -193,8 +193,6 @@ const FilePath::CharType kGDataCacheDirname[] = FPL("GCache");
const bool kRecordModeEnabled = true;
-const int kHistogramSynchronizerReservedSequenceNumber = 0;
-
const char* const kUnknownLanguageCode = "und";
const int kJavascriptMessageExpectedDelay = 1000;
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 1009976..12e4733 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -100,13 +100,6 @@ extern const FilePath::CharType kGDataCacheDirname[];
extern const bool kRecordModeEnabled;
-// Most sequence numbers are used by a renderer when responding to a browser
-// request for histogram data. This reserved number is used when a renderer
-// sends an unprovoked update, such as after a page has been loaded. Using
-// this reserved constant avoids any chance of confusion with a response having
-// a browser-supplied sequence number.
-extern const int kHistogramSynchronizerReservedSequenceNumber;
-
// The language code used when the language of a page could not be detected.
// (Matches what the CLD -Compact Language Detection- library reports.)
extern const char* const kUnknownLanguageCode;
diff --git a/chrome/common/metrics/histogram_sender.h b/chrome/common/metrics/histogram_sender.h
deleted file mode 100644
index ab597c6..0000000
--- a/chrome/common/metrics/histogram_sender.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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.
-
-#ifndef CHROME_COMMON_METRICS_HISTOGRAM_SENDER_H_
-#define CHROME_COMMON_METRICS_HISTOGRAM_SENDER_H_
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/metrics/histogram.h"
-
-// HistogramSender handles the logistics of gathering up available histograms
-// for transmission (such as from renderer to browser, or from browser to UMA
-// upload). It has several pure virtual functions that are replaced in
-// derived classes to allow the exact lower level transmission mechanism,
-// or error report mechanism, to be replaced. Since histograms can sit in
-// memory for an extended period of time, and are vulnerable to memory
-// corruption, this class also validates as much rendundancy as it can before
-// calling for the marginal change (a.k.a., delta) in a histogram to be sent
-// onward.
-class HistogramSender {
- protected:
- HistogramSender();
- virtual ~HistogramSender();
-
- // Snapshot all histograms, and transmit the delta.
- // The arguments allow a derived class to select only a subset for
- // transmission, or to set a flag in each transmitted histogram.
- void TransmitAllHistograms(base::Histogram::Flags flags_to_set,
- bool send_only_uma);
-
- // Send the histograms onward, as defined in a derived class.
- // This is only called with a delta, listing samples that have not previously
- // been transmitted.
- virtual void TransmitHistogramDelta(
- const base::Histogram& histogram,
- const base::Histogram::SampleSet& snapshot) = 0;
-
- // Record various errors found during attempts to send histograms.
- virtual void InconsistencyDetected(int problem) = 0;
- virtual void UniqueInconsistencyDetected(int problem) = 0;
- virtual void SnapshotProblemResolved(int amount) = 0;
-
- private:
- // Maintain a map of histogram names to the sample stats we've sent.
- typedef std::map<std::string, base::Histogram::SampleSet> LoggedSampleMap;
- // List of histograms names, and their encontered corruptions.
- typedef std::map<std::string, int> ProblemMap;
-
- // Snapshot this histogram, and transmit the delta.
- void TransmitHistogram(const base::Histogram& histogram);
-
- // For histograms, record what we've already transmitted (as a sample for each
- // histogram) so that we can send only the delta with the next log.
- LoggedSampleMap logged_samples_;
-
- // List of histograms found corrupt to be corrupt, and their problems.
- scoped_ptr<ProblemMap> inconsistencies_;
-
- DISALLOW_COPY_AND_ASSIGN(HistogramSender);
-};
-
-#endif // CHROME_COMMON_METRICS_HISTOGRAM_SENDER_H_
diff --git a/chrome/common/metrics/metrics_service_base.cc b/chrome/common/metrics/metrics_service_base.cc
index 42f84d7..a491578 100644
--- a/chrome/common/metrics/metrics_service_base.cc
+++ b/chrome/common/metrics/metrics_service_base.cc
@@ -10,7 +10,8 @@
using base::Histogram;
-MetricsServiceBase::MetricsServiceBase() {
+MetricsServiceBase::MetricsServiceBase()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(histogram_snapshot_manager_(this)) {
}
MetricsServiceBase::~MetricsServiceBase() {
@@ -31,10 +32,10 @@ const char MetricsServiceBase::kMimeTypeProto[] =
void MetricsServiceBase::RecordCurrentHistograms() {
DCHECK(log_manager_.current_log());
- TransmitAllHistograms(base::Histogram::kNoFlags, true);
+ histogram_snapshot_manager_.PrepareDeltas(base::Histogram::kNoFlags, true);
}
-void MetricsServiceBase::TransmitHistogramDelta(
+void MetricsServiceBase::RecordDelta(
const base::Histogram& histogram,
const base::Histogram::SampleSet& snapshot) {
log_manager_.current_log()->RecordHistogramDelta(histogram, snapshot);
diff --git a/chrome/common/metrics/metrics_service_base.h b/chrome/common/metrics/metrics_service_base.h
index 23b6a87..16fb6df 100644
--- a/chrome/common/metrics/metrics_service_base.h
+++ b/chrome/common/metrics/metrics_service_base.h
@@ -7,13 +7,22 @@
#include "base/basictypes.h"
#include "base/metrics/histogram.h"
-#include "chrome/common/metrics/histogram_sender.h"
+#include "base/metrics/histogram_flattener.h"
+#include "base/metrics/histogram_snapshot_manager.h"
#include "chrome/common/metrics/metrics_log_manager.h"
// This class provides base functionality for logging metrics data.
// TODO(ananta): Factor out more common code from chrome and chrome frame
// metrics service into this class.
-class MetricsServiceBase : public HistogramSender {
+class MetricsServiceBase : public base::HistogramFlattener {
+ public:
+ // HistogramFlattener interface (override) methods.
+ virtual void RecordDelta(const base::Histogram& histogram,
+ const base::Histogram::SampleSet& snapshot) OVERRIDE;
+ virtual void InconsistencyDetected(int problem) OVERRIDE;
+ virtual void UniqueInconsistencyDetected(int problem) OVERRIDE;
+ virtual void SnapshotProblemResolved(int amount) OVERRIDE;
+
protected:
MetricsServiceBase();
virtual ~MetricsServiceBase();
@@ -34,13 +43,8 @@ class MetricsServiceBase : public HistogramSender {
MetricsLogManager log_manager_;
private:
- // HistogramSender interface (override) methods.
- virtual void TransmitHistogramDelta(
- const base::Histogram& histogram,
- const base::Histogram::SampleSet& snapshot) OVERRIDE;
- virtual void InconsistencyDetected(int problem) OVERRIDE;
- virtual void UniqueInconsistencyDetected(int problem) OVERRIDE;
- virtual void SnapshotProblemResolved(int amount) OVERRIDE;
+ // |histogram_snapshot_manager_| prepares histogram deltas for transmission.
+ base::HistogramSnapshotManager histogram_snapshot_manager_;
DISALLOW_COPY_AND_ASSIGN(MetricsServiceBase);
};
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index c4191ca..cea44c4 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -238,10 +238,6 @@ IPC_MESSAGE_ROUTED1(ChromeViewMsg_LoadBlockedPlugins,
// resource types.
IPC_MESSAGE_CONTROL0(ChromeViewMsg_GetCacheResourceStats)
-// Asks the renderer to send back Histograms.
-IPC_MESSAGE_CONTROL1(ChromeViewMsg_GetRendererHistograms,
- int /* sequence number of Renderer Histograms. */)
-
// Tells the renderer to create a FieldTrial, and by using a 100% probability
// for the FieldTrial, forces the FieldTrial to have assigned group name.
IPC_MESSAGE_CONTROL2(ChromeViewMsg_SetFieldTrialGroup,
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 425dc83..788e49d 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -157,7 +157,6 @@ const char kChromeUIGpuInternalsHost[] = "gpu-internals";
const char kChromeUIHangHost[] = "hang";
const char kChromeUIHelpFrameHost[] = "help-frame";
const char kChromeUIHelpHost[] = "help";
-const char kChromeUIHistogramsHost[] = "histograms";
const char kChromeUIHistoryHost[] = "history";
const char kChromeUIHistoryFrameHost[] = "history-frame";
const char kChromeUIInputWindowDialogHost[] = "input-window-dialog";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 50dab9b..a3c7211 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -148,7 +148,6 @@ extern const char kChromeUIHelpHost[];
extern const char kChromeUIGpuHost[];
extern const char kChromeUIGpuInternalsHost[];
extern const char kChromeUIHangHost[];
-extern const char kChromeUIHistogramsHost[];
extern const char kChromeUIHistoryHost[];
extern const char kChromeUIHistoryFrameHost[];
extern const char kChromeUIInputWindowDialogHost[];
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 76f6020..764874a 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -55,7 +55,6 @@
#include "chrome/renderer/prerender/prerender_webmediaplayer.h"
#include "chrome/renderer/prerender/prerenderer_client.h"
#include "chrome/renderer/print_web_view_helper.h"
-#include "chrome/renderer/renderer_histogram_snapshots.h"
#include "chrome/renderer/safe_browsing/malware_dom_details.h"
#include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
#include "chrome/renderer/search_extension.h"
@@ -155,7 +154,6 @@ ChromeContentRendererClient::~ChromeContentRendererClient() {
void ChromeContentRendererClient::RenderThreadStarted() {
chrome_observer_.reset(new ChromeRenderProcessObserver(this));
extension_dispatcher_.reset(new ExtensionDispatcher());
- histogram_snapshots_.reset(new RendererHistogramSnapshots());
net_predictor_.reset(new RendererNetPredictor());
spellcheck_.reset(new SpellCheck());
visited_link_slave_.reset(new VisitedLinkSlave());
@@ -168,7 +166,6 @@ void ChromeContentRendererClient::RenderThreadStarted() {
thread->AddObserver(chrome_observer_.get());
thread->AddObserver(extension_dispatcher_.get());
- thread->AddObserver(histogram_snapshots_.get());
#if defined(ENABLE_SAFE_BROWSING)
thread->AddObserver(phishing_classifier_.get());
#endif
@@ -253,7 +250,7 @@ void ChromeContentRendererClient::RenderViewCreated(
chrome_observer_->content_setting_rules());
}
new ExtensionHelper(render_view, extension_dispatcher_.get());
- new PageLoadHistograms(render_view, histogram_snapshots_.get());
+ new PageLoadHistograms(render_view);
#if defined(ENABLE_PRINTING)
new PrintWebViewHelper(render_view);
#endif
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index c85560a..6c4a28f 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -16,7 +16,6 @@
class ChromeRenderProcessObserver;
class ExtensionDispatcher;
class ExtensionSet;
-class RendererHistogramSnapshots;
class RendererNetPredictor;
class SpellCheck;
class SpellCheckProvider;
@@ -159,7 +158,6 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
scoped_ptr<ChromeRenderProcessObserver> chrome_observer_;
scoped_ptr<ExtensionDispatcher> extension_dispatcher_;
- scoped_ptr<RendererHistogramSnapshots> histogram_snapshots_;
scoped_ptr<RendererNetPredictor> net_predictor_;
scoped_ptr<SpellCheck> spellcheck_;
scoped_ptr<VisitedLinkSlave> visited_link_slave_;
diff --git a/chrome/renderer/page_load_histograms.cc b/chrome/renderer/page_load_histograms.cc
index ce8a529..2b7c026 100644
--- a/chrome/renderer/page_load_histograms.cc
+++ b/chrome/renderer/page_load_histograms.cc
@@ -8,12 +8,12 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/time.h"
-#include "chrome/common/chrome_constants.h"
#include "chrome/common/extensions/url_pattern.h"
#include "chrome/renderer/chrome_content_renderer_client.h"
#include "chrome/renderer/prerender/prerender_helper.h"
-#include "chrome/renderer/renderer_histogram_snapshots.h"
+#include "content/public/common/content_constants.h"
#include "content/public/renderer/document_state.h"
+#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
@@ -118,13 +118,10 @@ enum AbandonType {
} // namespace
-PageLoadHistograms::PageLoadHistograms(
- content::RenderView* render_view,
- RendererHistogramSnapshots* histogram_snapshots)
+PageLoadHistograms::PageLoadHistograms(content::RenderView* render_view)
: content::RenderViewObserver(render_view),
cross_origin_access_count_(0),
- same_origin_access_count_(0),
- histogram_snapshots_(histogram_snapshots) {
+ same_origin_access_count_(0) {
}
void PageLoadHistograms::Dump(WebFrame* frame) {
@@ -942,8 +939,8 @@ void PageLoadHistograms::Dump(WebFrame* frame) {
// TODO(jar) BUG=33233: This needs to be moved to a PostDelayedTask, and it
// should post when the onload is complete, so that it doesn't interfere with
// the next load.
- histogram_snapshots_->SendHistograms(
- chrome::kHistogramSynchronizerReservedSequenceNumber);
+ content::RenderThread::Get()->UpdateHistograms(
+ content::kHistogramSynchronizerReservedSequenceNumber);
}
void PageLoadHistograms::ResetCrossFramePropertyAccess() {
diff --git a/chrome/renderer/page_load_histograms.h b/chrome/renderer/page_load_histograms.h
index ccf3ddb..ac0111e 100644
--- a/chrome/renderer/page_load_histograms.h
+++ b/chrome/renderer/page_load_histograms.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -12,12 +12,9 @@ namespace content {
class DocumentState;
}
-class RendererHistogramSnapshots;
-
class PageLoadHistograms : public content::RenderViewObserver {
public:
- PageLoadHistograms(content::RenderView* render_view,
- RendererHistogramSnapshots* histogram_snapshots);
+ explicit PageLoadHistograms(content::RenderView* render_view);
private:
// RenderViewObserver implementation.
@@ -55,8 +52,6 @@ class PageLoadHistograms : public content::RenderViewObserver {
int cross_origin_access_count_;
int same_origin_access_count_;
- RendererHistogramSnapshots* histogram_snapshots_;
-
DISALLOW_COPY_AND_ASSIGN(PageLoadHistograms);
};
diff --git a/chrome/renderer/renderer_histogram_snapshots.cc b/chrome/renderer/renderer_histogram_snapshots.cc
deleted file mode 100644
index 297d693..0000000
--- a/chrome/renderer/renderer_histogram_snapshots.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "chrome/renderer/renderer_histogram_snapshots.h"
-
-#include <ctype.h>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/metrics/histogram.h"
-#include "chrome/common/render_messages.h"
-#include "content/public/renderer/render_thread.h"
-
-// TODO(raman): Before renderer shuts down send final snapshot lists.
-
-using base::Histogram;
-using base::StatisticsRecorder;
-using content::RenderThread;
-
-RendererHistogramSnapshots::RendererHistogramSnapshots()
- : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
-}
-
-RendererHistogramSnapshots::~RendererHistogramSnapshots() {
-}
-
-// Send data quickly!
-void RendererHistogramSnapshots::SendHistograms(int sequence_number) {
- RenderThread::Get()->GetMessageLoop()->PostTask(
- FROM_HERE, base::Bind(&RendererHistogramSnapshots::UploadAllHistrograms,
- weak_factory_.GetWeakPtr(), sequence_number));
-}
-
-bool RendererHistogramSnapshots::OnControlMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RendererHistogramSnapshots, message)
- IPC_MESSAGE_HANDLER(ChromeViewMsg_GetRendererHistograms,
- OnGetRendererHistograms)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void RendererHistogramSnapshots::OnGetRendererHistograms(int sequence_number) {
- SendHistograms(sequence_number);
-}
-
-void RendererHistogramSnapshots::UploadAllHistrograms(int sequence_number) {
- DCHECK_EQ(0u, pickled_histograms_.size());
-
- StatisticsRecorder::CollectHistogramStats("Renderer");
-
- // Push snapshots into our pickled_histograms_ vector.
- TransmitAllHistograms(Histogram::kIPCSerializationSourceFlag, false);
-
- // Send the sequence number and list of pickled histograms over synchronous
- // IPC, so we can clear pickled_histograms_ afterwards.
- RenderThread::Get()->Send(new ChromeViewHostMsg_RendererHistograms(
- sequence_number, pickled_histograms_));
-
- pickled_histograms_.clear();
-}
-
-void RendererHistogramSnapshots::TransmitHistogramDelta(
- const base::Histogram& histogram,
- const base::Histogram::SampleSet& snapshot) {
- DCHECK_NE(0, snapshot.TotalCount());
- snapshot.CheckSize(histogram);
-
- std::string histogram_info =
- Histogram::SerializeHistogramInfo(histogram, snapshot);
- pickled_histograms_.push_back(histogram_info);
-}
-
-void RendererHistogramSnapshots::InconsistencyDetected(int problem) {
- UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesRenderer",
- problem, Histogram::NEVER_EXCEEDED_VALUE);
-}
-
-void RendererHistogramSnapshots::UniqueInconsistencyDetected(int problem) {
- UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesRendererUnique",
- problem, Histogram::NEVER_EXCEEDED_VALUE);
-}
-
-void RendererHistogramSnapshots::SnapshotProblemResolved(int amount) {
- UMA_HISTOGRAM_COUNTS("Histogram.InconsistentSnapshotRenderer",
- std::abs(amount));
-}
-
diff --git a/chrome/renderer/renderer_histogram_snapshots.h b/chrome/renderer/renderer_histogram_snapshots.h
deleted file mode 100644
index 6da9bc0..0000000
--- a/chrome/renderer/renderer_histogram_snapshots.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.
-
-#ifndef CHROME_RENDERER_RENDERER_HISTOGRAM_SNAPSHOTS_H_
-#define CHROME_RENDERER_RENDERER_HISTOGRAM_SNAPSHOTS_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram.h"
-#include "base/process.h"
-#include "chrome/common/metrics/histogram_sender.h"
-#include "content/public/renderer/render_process_observer.h"
-
-class RendererHistogramSnapshots : public HistogramSender,
- public content::RenderProcessObserver {
- public:
- RendererHistogramSnapshots();
- virtual ~RendererHistogramSnapshots();
-
- // Send the histogram data.
- void SendHistograms(int sequence_number);
-
- private:
- // RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
-
- void OnGetRendererHistograms(int sequence_number);
-
- // Maintain a map of histogram names to the sample stats we've sent.
- typedef std::map<std::string, base::Histogram::SampleSet> LoggedSampleMap;
- typedef std::vector<std::string> HistogramPickledList;
-
- // Extract snapshot data and then send it off the the Browser process.
- // Send only a delta to what we have already sent.
- void UploadAllHistrograms(int sequence_number);
-
- base::WeakPtrFactory<RendererHistogramSnapshots> weak_factory_;
-
- // HistogramSender interface (override) methods.
- virtual void TransmitHistogramDelta(
- const base::Histogram& histogram,
- const base::Histogram::SampleSet& snapshot) OVERRIDE;
- virtual void InconsistencyDetected(int problem) OVERRIDE;
- virtual void UniqueInconsistencyDetected(int problem) OVERRIDE;
- virtual void SnapshotProblemResolved(int amount) OVERRIDE;
-
- // Collection of histograms to send to the browser.
- HistogramPickledList pickled_histograms_;
-
- DISALLOW_COPY_AND_ASSIGN(RendererHistogramSnapshots);
-};
-
-#endif // CHROME_RENDERER_RENDERER_HISTOGRAM_SNAPSHOTS_H_
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index 00076d9..ffceeff 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -14,6 +14,7 @@
#include "base/process_util.h"
#include "base/stl_util.h"
#include "base/string_util.h"
+#include "content/browser/histogram_message_filter.h"
#include "content/browser/profiler_message_filter.h"
#include "content/browser/renderer_host/resource_message_filter.h"
#include "content/browser/trace_message_filter.h"
@@ -85,6 +86,7 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
child_process_host_.reset(ChildProcessHost::Create(this));
child_process_host_->AddFilter(new TraceMessageFilter);
child_process_host_->AddFilter(new content::ProfilerMessageFilter(type));
+ child_process_host_->AddFilter(new content::HistogramMessageFilter());
g_child_process_list.Get().push_back(this);
content::GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
diff --git a/content/browser/histogram_controller.cc b/content/browser/histogram_controller.cc
new file mode 100644
index 0000000..086e6ea
--- /dev/null
+++ b/content/browser/histogram_controller.cc
@@ -0,0 +1,112 @@
+// 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.
+
+#include "content/browser/histogram_controller.h"
+
+#include "base/bind.h"
+#include "base/metrics/histogram.h"
+#include "content/browser/histogram_subscriber.h"
+#include "content/common/child_process_messages.h"
+#include "content/public/browser/browser_child_process_host_iterator.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/render_process_host.h"
+
+namespace content {
+
+HistogramController* HistogramController::GetInstance() {
+ return Singleton<HistogramController>::get();
+}
+
+HistogramController::HistogramController() : subscriber_(NULL) {
+}
+
+HistogramController::~HistogramController() {
+}
+
+void HistogramController::OnPendingProcesses(int sequence_number,
+ int pending_processes,
+ bool end) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (subscriber_)
+ subscriber_->OnPendingProcesses(sequence_number, pending_processes, end);
+}
+
+void HistogramController::OnHistogramDataCollected(
+ int sequence_number,
+ const std::vector<std::string>& pickled_histograms) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&HistogramController::OnHistogramDataCollected,
+ base::Unretained(this),
+ sequence_number,
+ pickled_histograms));
+ return;
+ }
+
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (subscriber_) {
+ subscriber_->OnHistogramDataCollected(sequence_number,
+ pickled_histograms);
+ }
+}
+
+void HistogramController::Register(HistogramSubscriber* subscriber) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!subscriber_);
+ subscriber_ = subscriber;
+}
+
+void HistogramController::Unregister(
+ const HistogramSubscriber* subscriber) {
+ DCHECK_EQ(subscriber_, subscriber);
+ subscriber_ = NULL;
+}
+
+void HistogramController::GetHistogramDataFromChildProcesses(
+ int sequence_number) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ int pending_processes = 0;
+ for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
+ ++pending_processes;
+ if (!iter.Send(new ChildProcessMsg_GetChildHistogramData(sequence_number)))
+ --pending_processes;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &HistogramController::OnPendingProcesses,
+ base::Unretained(this),
+ sequence_number,
+ pending_processes,
+ true));
+}
+
+void HistogramController::GetHistogramData(int sequence_number) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ int pending_processes = 0;
+ for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
+ !it.IsAtEnd(); it.Advance()) {
+ ++pending_processes;
+ if (!it.GetCurrentValue()->Send(
+ new ChildProcessMsg_GetChildHistogramData(sequence_number))) {
+ --pending_processes;
+ }
+ }
+ OnPendingProcesses(sequence_number, pending_processes, false);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&HistogramController::GetHistogramDataFromChildProcesses,
+ base::Unretained(this),
+ sequence_number));
+}
+
+} // namespace content
diff --git a/content/browser/histogram_controller.h b/content/browser/histogram_controller.h
new file mode 100644
index 0000000..01892e9
--- /dev/null
+++ b/content/browser/histogram_controller.h
@@ -0,0 +1,70 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_HISTOGRAM_CONTROLLER_H_
+#define CONTENT_BROWSER_HISTOGRAM_CONTROLLER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/singleton.h"
+
+namespace content {
+
+class HistogramSubscriber;
+
+// HistogramController is used on the browser process to collect histogram data.
+// Only the browser UI thread is allowed to interact with the
+// HistogramController object.
+class HistogramController {
+ public:
+ // Returns the HistogramController object for the current process, or NULL if
+ // none.
+ static HistogramController* GetInstance();
+
+ // Normally instantiated when the child process is launched. Only one instance
+ // should be created per process.
+ HistogramController();
+ virtual ~HistogramController();
+
+ // Register the subscriber so that it will be called when for example
+ // OnHistogramDataCollected is returning histogram data from a child process.
+ // This is called on UI thread.
+ void Register(HistogramSubscriber* subscriber);
+
+ // Unregister the subscriber so that it will not be called when for example
+ // OnHistogramDataCollected is returning histogram data from a child process.
+ // Safe to call even if caller is not the current subscriber.
+ void Unregister(const HistogramSubscriber* subscriber);
+
+ // Contact all processes and get their histogram data.
+ void GetHistogramData(int sequence_number);
+
+ // Notify the |subscriber_| that it should expect at least |pending_processes|
+ // additional calls to OnHistogramDataCollected(). OnPendingProcess() may be
+ // called repeatedly; the last call will have |end| set to true, indicating
+ // that there is no longer a possibility for the count of pending processes to
+ // increase. This is called on the UI thread.
+ void OnPendingProcesses(int sequence_number, int pending_processes, bool end);
+
+ // Send the |histogram| back to the |subscriber_|.
+ // This can be called from any thread.
+ void OnHistogramDataCollected(
+ int sequence_number,
+ const std::vector<std::string>& pickled_histograms);
+
+ private:
+ friend struct DefaultSingletonTraits<HistogramController>;
+
+ // Contact child processes and get their histogram data.
+ void GetHistogramDataFromChildProcesses(int sequence_number);
+
+ HistogramSubscriber* subscriber_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistogramController);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_HISTOGRAM_CONTROLLER_H_
diff --git a/content/browser/histogram_internals_request_job.cc b/content/browser/histogram_internals_request_job.cc
new file mode 100644
index 0000000..cb3c8fc
--- /dev/null
+++ b/content/browser/histogram_internals_request_job.cc
@@ -0,0 +1,72 @@
+// 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.
+
+#include "content/browser/histogram_internals_request_job.h"
+
+#include "base/metrics/histogram.h"
+#include "content/browser/histogram_synchronizer.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/escape.h"
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+HistogramInternalsRequestJob::HistogramInternalsRequestJob(
+ net::URLRequest* request) : net::URLRequestSimpleJob(request) {
+ const std::string& spec = request->url().possibly_invalid_spec();
+ const url_parse::Parsed& parsed =
+ request->url().parsed_for_possibly_invalid_spec();
+ // + 1 to skip the slash at the beginning of the path.
+ int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false) + 1;
+
+ if (offset < static_cast<int>(spec.size()))
+ path_.assign(spec.substr(offset));
+}
+
+void AboutHistogram(std::string* data, const std::string& path) {
+#ifndef NDEBUG
+ // We only rush the acquisition of Histogram meta-data (meta-histograms) in
+ // Debug mode, so that developers don't damage our data that we upload to UMA
+ // (in official builds).
+ base::StatisticsRecorder::CollectHistogramStats("Browser");
+#endif
+ content::HistogramSynchronizer::FetchHistograms();
+
+ std::string unescaped_query;
+ std::string unescaped_title("About Histograms");
+ if (!path.empty()) {
+ unescaped_query = net::UnescapeURLComponent(path,
+ net::UnescapeRule::NORMAL);
+ unescaped_title += " - " + unescaped_query;
+ }
+
+ data->append("<!DOCTYPE html>\n<html>\n<head>\n");
+ data->append(
+ "<meta http-equiv=\"X-WebKit-CSP\" content=\"object-src 'none'; "
+ "script-src 'none' 'unsafe-eval'\">");
+ data->append("<title>");
+ data->append(net::EscapeForHTML(unescaped_title));
+ data->append("</title>\n");
+ data->append("</head><body>");
+
+ // Display any stats for which we sent off requests the last time.
+ data->append("<p>Stats as of last page load;");
+ data->append("reload to get stats as of this page load.</p>\n");
+ data->append("<table width=\"100%\">\n");
+
+ base::StatisticsRecorder::WriteHTMLGraph(unescaped_query, data);
+}
+
+bool HistogramInternalsRequestJob::GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data) const {
+ mime_type->assign("text/html");
+ charset->assign("UTF8");
+
+ data->clear();
+ AboutHistogram(data, path_);
+ return true;
+}
+
+} // namespace content
diff --git a/content/browser/histogram_internals_request_job.h b/content/browser/histogram_internals_request_job.h
new file mode 100644
index 0000000..0613af3
--- /dev/null
+++ b/content/browser/histogram_internals_request_job.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_HISTOGRAM_INTERNALS_REQUEST_JOB_H_
+#define CONTENT_BROWSER_HISTOGRAM_INTERNALS_REQUEST_JOB_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "net/url_request/url_request_simple_job.h"
+
+namespace content {
+
+class HistogramInternalsRequestJob : public net::URLRequestSimpleJob {
+ public:
+ explicit HistogramInternalsRequestJob(net::URLRequest* request);
+
+ virtual bool GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data) const OVERRIDE;
+
+ private:
+ virtual ~HistogramInternalsRequestJob() {}
+
+ // The string to select histograms which have |path_| as a substring.
+ std::string path_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(HistogramInternalsRequestJob);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_HISTOGRAM_INTERNALS_REQUEST_JOB_H_
diff --git a/content/browser/histogram_message_filter.cc b/content/browser/histogram_message_filter.cc
new file mode 100644
index 0000000..959c280
--- /dev/null
+++ b/content/browser/histogram_message_filter.cc
@@ -0,0 +1,40 @@
+// 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.
+
+#include "content/browser/histogram_message_filter.h"
+
+#include "base/process_util.h"
+#include "content/browser/histogram_controller.h"
+#include "content/browser/tcmalloc_internals_request_job.h"
+#include "content/common/child_process_messages.h"
+
+namespace content {
+
+HistogramMessageFilter::HistogramMessageFilter() {
+}
+
+void HistogramMessageFilter::OnChannelConnected(int32 peer_pid) {
+ BrowserMessageFilter::OnChannelConnected(peer_pid);
+}
+
+bool HistogramMessageFilter::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(HistogramMessageFilter, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ChildHistogramData,
+ OnChildHistogramData)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+ return handled;
+}
+
+HistogramMessageFilter::~HistogramMessageFilter() {}
+
+void HistogramMessageFilter::OnChildHistogramData(
+ int sequence_number,
+ const std::vector<std::string>& pickled_histograms) {
+ HistogramController::GetInstance()->OnHistogramDataCollected(
+ sequence_number, pickled_histograms);
+}
+}
diff --git a/content/browser/histogram_message_filter.h b/content/browser/histogram_message_filter.h
new file mode 100644
index 0000000..b8ca89d
--- /dev/null
+++ b/content/browser/histogram_message_filter.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_HISTOGRAM_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_HISTOGRAM_MESSAGE_FILTER_H_
+
+#include <string>
+#include <vector>
+
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/common/process_type.h"
+
+namespace content {
+
+// This class sends and receives histogram messages in the browser process.
+class HistogramMessageFilter : public BrowserMessageFilter {
+ public:
+ HistogramMessageFilter();
+
+ // content::BrowserMessageFilter implementation.
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+
+ // content::BrowserMessageFilter implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+
+ private:
+ virtual ~HistogramMessageFilter();
+
+ // Message handlers.
+ void OnChildHistogramData(int sequence_number,
+ const std::vector<std::string>& pickled_histograms);
+
+ ProcessType process_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistogramMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_HISTOGRAM_MESSAGE_FILTER_H_
diff --git a/content/browser/histogram_subscriber.h b/content/browser/histogram_subscriber.h
new file mode 100644
index 0000000..993e4c9
--- /dev/null
+++ b/content/browser/histogram_subscriber.h
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_HISTOGRAM_SUBSCRIBER_H_
+#define CONTENT_BROWSER_HISTOGRAM_SUBSCRIBER_H_
+
+#include <string>
+#include <vector>
+
+namespace content {
+
+// Objects interested in receiving histograms derive from HistogramSubscriber.
+class HistogramSubscriber {
+ public:
+ virtual ~HistogramSubscriber() {}
+
+ // Send number of pending processes to subscriber. |end| is set to true if it
+ // is the last time. This is called on the UI thread.
+ virtual void OnPendingProcesses(int sequence_number,
+ int pending_processes,
+ bool end) = 0;
+
+ // Send |histogram| back to subscriber.
+ // This is called on the UI thread.
+ virtual void OnHistogramDataCollected(
+ int sequence_number,
+ const std::vector<std::string>& pickled_histograms) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_HISTOGRAM_SUBSCRIBER_H_
diff --git a/content/browser/histogram_synchronizer.cc b/content/browser/histogram_synchronizer.cc
new file mode 100644
index 0000000..bb90b07
--- /dev/null
+++ b/content/browser/histogram_synchronizer.cc
@@ -0,0 +1,346 @@
+// 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.
+
+#include "content/browser/histogram_synchronizer.h"
+
+#include "base/bind.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "content/browser/histogram_controller.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/histogram_fetcher.h"
+#include "content/public/common/content_constants.h"
+
+using base::Time;
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace {
+
+// Negative numbers are never used as sequence numbers. We explicitly pick a
+// negative number that is "so negative" that even when we add one (as is done
+// when we generated the next sequence number) that it will still be negative.
+// We have code that handles wrapping around on an overflow into negative
+// territory.
+static const int kNeverUsableSequenceNumber = -2;
+
+} // anonymous namespace
+
+namespace content {
+
+// The "RequestContext" structure describes an individual request received from
+// the UI. All methods are accessible on UI thread.
+class HistogramSynchronizer::RequestContext {
+ public:
+ // A map from sequence_number_ to the actual RequestContexts.
+ typedef std::map<int, RequestContext*> RequestContextMap;
+
+ RequestContext(const base::Closure& callback, int sequence_number)
+ : callback_(callback),
+ sequence_number_(sequence_number),
+ received_process_group_count_(0),
+ processes_pending_(0) {
+ }
+ ~RequestContext() {}
+
+ void SetReceivedProcessGroupCount(bool done) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ received_process_group_count_ = done;
+ }
+
+ // Methods for book keeping of processes_pending_.
+ void AddProcessesPending(int processes_pending) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ processes_pending_ += processes_pending;
+ }
+
+ void DecrementProcessesPending() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ --processes_pending_;
+ }
+
+ // Records that we are waiting for one less histogram data from a process for
+ // the given sequence number. If |received_process_group_count_| and
+ // |processes_pending_| are zero, then delete the current object by calling
+ // Unregister.
+ void DeleteIfAllDone() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (processes_pending_ <= 0 && received_process_group_count_)
+ RequestContext::Unregister(sequence_number_);
+ }
+
+ // Register |callback| in |outstanding_requests_| map for the given
+ // |sequence_number|.
+ static void Register(const base::Closure& callback, int sequence_number) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ RequestContext* request = new RequestContext(callback, sequence_number);
+ outstanding_requests_.Get()[sequence_number] = request;
+ }
+
+ // Find the |RequestContext| in |outstanding_requests_| map for the given
+ // |sequence_number|.
+ static RequestContext* GetRequestContext(int sequence_number) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ RequestContextMap::iterator it =
+ outstanding_requests_.Get().find(sequence_number);
+ if (it == outstanding_requests_.Get().end())
+ return NULL;
+
+ RequestContext* request = it->second;
+ DCHECK_EQ(sequence_number, request->sequence_number_);
+ return request;
+ }
+
+ // Delete the entry for the given |sequence_number| from
+ // |outstanding_requests_| map. This method is called when all changes have
+ // been acquired, or when the wait time expires (whichever is sooner).
+ static void Unregister(int sequence_number) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ RequestContextMap::iterator it =
+ outstanding_requests_.Get().find(sequence_number);
+ if (it == outstanding_requests_.Get().end())
+ return;
+
+ RequestContext* request = it->second;
+ DCHECK_EQ(sequence_number, request->sequence_number_);
+ bool received_process_group_count = request->received_process_group_count_;
+ int unresponsive_processes = request->processes_pending_;
+
+ request->callback_.Run();
+
+ delete request;
+ outstanding_requests_.Get().erase(it);
+
+ UMA_HISTOGRAM_BOOLEAN("Histogram.ReceivedProcessGroupCount",
+ received_process_group_count);
+ UMA_HISTOGRAM_COUNTS("Histogram.PendingProcessNotResponding",
+ unresponsive_processes);
+ }
+
+ // Delete all the entries in |outstanding_requests_| map.
+ static void OnShutdown() {
+ // Just in case we have any pending tasks, clear them out.
+ while (!outstanding_requests_.Get().empty()) {
+ RequestContextMap::iterator it = outstanding_requests_.Get().begin();
+ delete it->second;
+ outstanding_requests_.Get().erase(it);
+ }
+ }
+
+ // Requests are made to asynchronously send data to the |callback_|.
+ base::Closure callback_;
+
+ // The sequence number used by the most recent update request to contact all
+ // processes.
+ int sequence_number_;
+
+ // Indicates if we have received all pending processes count.
+ bool received_process_group_count_;
+
+ // The number of pending processes (all renderer processes and browser child
+ // processes) that have not yet responded to requests.
+ int processes_pending_;
+
+ // Map of all outstanding RequestContexts, from sequence_number_ to
+ // RequestContext.
+ static base::LazyInstance<RequestContextMap>::Leaky outstanding_requests_;
+};
+
+// static
+base::LazyInstance
+ <HistogramSynchronizer::RequestContext::RequestContextMap>::Leaky
+ HistogramSynchronizer::RequestContext::outstanding_requests_ =
+ LAZY_INSTANCE_INITIALIZER;
+
+HistogramSynchronizer::HistogramSynchronizer()
+ : lock_(),
+ callback_thread_(NULL),
+ last_used_sequence_number_(kNeverUsableSequenceNumber),
+ async_sequence_number_(kNeverUsableSequenceNumber) {
+ content::HistogramController::GetInstance()->Register(this);
+}
+
+HistogramSynchronizer::~HistogramSynchronizer() {
+ RequestContext::OnShutdown();
+
+ // Just in case we have any pending tasks, clear them out.
+ SetCallbackTaskAndThread(NULL, base::Closure());
+}
+
+HistogramSynchronizer* HistogramSynchronizer::GetInstance() {
+ return Singleton<HistogramSynchronizer,
+ LeakySingletonTraits<HistogramSynchronizer> >::get();
+}
+
+// static
+void HistogramSynchronizer::FetchHistograms() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&HistogramSynchronizer::FetchHistograms));
+ return;
+ }
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ HistogramSynchronizer* current_synchronizer =
+ HistogramSynchronizer::GetInstance();
+ if (current_synchronizer == NULL)
+ return;
+
+ current_synchronizer->RegisterAndNotifyAllProcesses(
+ HistogramSynchronizer::UNKNOWN,
+ base::TimeDelta::FromMinutes(1));
+}
+
+void FetchHistogramsAsynchronously(MessageLoop* callback_thread,
+ const base::Closure& callback,
+ base::TimeDelta wait_time) {
+ HistogramSynchronizer::FetchHistogramsAsynchronously(
+ callback_thread, callback, wait_time);
+}
+
+// static
+void HistogramSynchronizer::FetchHistogramsAsynchronously(
+ MessageLoop* callback_thread,
+ const base::Closure& callback,
+ base::TimeDelta wait_time) {
+ DCHECK(callback_thread != NULL);
+ DCHECK(!callback.is_null());
+
+ HistogramSynchronizer* current_synchronizer =
+ HistogramSynchronizer::GetInstance();
+ current_synchronizer->SetCallbackTaskAndThread(
+ callback_thread, callback);
+
+ current_synchronizer->RegisterAndNotifyAllProcesses(
+ HistogramSynchronizer::ASYNC_HISTOGRAMS, wait_time);
+}
+
+void HistogramSynchronizer::RegisterAndNotifyAllProcesses(
+ ProcessHistogramRequester requester,
+ base::TimeDelta wait_time) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ int sequence_number = GetNextAvailableSequenceNumber(requester);
+
+ base::Closure callback = base::Bind(
+ &HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback,
+ base::Unretained(this),
+ sequence_number);
+
+ RequestContext::Register(callback, sequence_number);
+
+ // Get histogram data from renderer and browser child processes.
+ content::HistogramController::GetInstance()->GetHistogramData(
+ sequence_number);
+
+ // Post a task that would be called after waiting for wait_time. This acts
+ // as a watchdog, to cancel the requests for non-responsive processes.
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&RequestContext::Unregister, sequence_number),
+ wait_time);
+}
+
+void HistogramSynchronizer::OnPendingProcesses(int sequence_number,
+ int pending_processes,
+ bool end) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ RequestContext* request = RequestContext::GetRequestContext(sequence_number);
+ if (!request)
+ return;
+ request->AddProcessesPending(pending_processes);
+ request->SetReceivedProcessGroupCount(end);
+ request->DeleteIfAllDone();
+}
+
+void HistogramSynchronizer::OnHistogramDataCollected(
+ int sequence_number,
+ const std::vector<std::string>& pickled_histograms) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ RequestContext* request = RequestContext::GetRequestContext(sequence_number);
+
+ for (std::vector<std::string>::const_iterator it = pickled_histograms.begin();
+ it < pickled_histograms.end();
+ ++it) {
+ base::Histogram::DeserializeHistogramInfo(*it);
+ }
+
+ if (!request)
+ return;
+
+ // Delete request if we have heard back from all child processes.
+ request->DecrementProcessesPending();
+ request->DeleteIfAllDone();
+}
+
+void HistogramSynchronizer::SetCallbackTaskAndThread(
+ MessageLoop* callback_thread,
+ const base::Closure& callback) {
+ base::Closure old_callback;
+ MessageLoop* old_thread = NULL;
+ {
+ base::AutoLock auto_lock(lock_);
+ old_callback = callback_;
+ callback_ = callback;
+ old_thread = callback_thread_;
+ callback_thread_ = callback_thread;
+ // Prevent premature calling of our new callbacks.
+ async_sequence_number_ = kNeverUsableSequenceNumber;
+ }
+ // Just in case there was a task pending....
+ InternalPostTask(old_thread, old_callback);
+}
+
+void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback(
+ int sequence_number) {
+ base::Closure callback;
+ MessageLoop* thread = NULL;
+ {
+ base::AutoLock lock(lock_);
+ if (sequence_number != async_sequence_number_)
+ return;
+ callback = callback_;
+ thread = callback_thread_;
+ callback_.Reset();
+ callback_thread_ = NULL;
+ }
+ InternalPostTask(thread, callback);
+}
+
+void HistogramSynchronizer::InternalPostTask(MessageLoop* thread,
+ const base::Closure& callback) {
+ if (callback.is_null() || !thread)
+ return;
+ thread->PostTask(FROM_HERE, callback);
+}
+
+int HistogramSynchronizer::GetNextAvailableSequenceNumber(
+ ProcessHistogramRequester requester) {
+ base::AutoLock auto_lock(lock_);
+ ++last_used_sequence_number_;
+ // Watch out for wrapping to a negative number.
+ if (last_used_sequence_number_ < 0) {
+ // Bypass the reserved number, which is used when a renderer spontaneously
+ // decides to send some histogram data.
+ last_used_sequence_number_ =
+ kHistogramSynchronizerReservedSequenceNumber + 1;
+ }
+ DCHECK_NE(last_used_sequence_number_,
+ kHistogramSynchronizerReservedSequenceNumber);
+ if (requester == ASYNC_HISTOGRAMS)
+ async_sequence_number_ = last_used_sequence_number_;
+ return last_used_sequence_number_;
+}
+
+} // namespace content
diff --git a/content/browser/histogram_synchronizer.h b/content/browser/histogram_synchronizer.h
new file mode 100644
index 0000000..3e68d3c
--- /dev/null
+++ b/content/browser/histogram_synchronizer.h
@@ -0,0 +1,151 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
+#define CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+#include "base/time.h"
+#include "content/browser/histogram_subscriber.h"
+
+class MessageLoop;
+
+namespace content {
+
+// This class maintains state that is used to upload histogram data from the
+// various child processes, into the browser process. Such transactions are
+// usually instigated by the browser. In general, a child process will respond
+// by gathering snapshots of all internal histograms, calculating what has
+// changed since its last upload, and transmitting a pickled collection of
+// deltas.
+//
+// There are actually two modes of update request. One is synchronous (and
+// blocks the UI thread, waiting to populate an about:histograms tab) and the
+// other is asynchronous, and used by the metrics services in preparation for a
+// log upload.
+//
+// To assure that all the processes have responded, a counter is maintained to
+// indicate the number of pending (not yet responsive) processes. To avoid
+// confusion about a response (i.e., is the process responding to a current
+// request for an update, or to an old request for an update) we tag each group
+// of requests with a sequence number. When an update arrives we can ignore it
+// (relative to the counter) if it does not relate to a current outstanding
+// sequence number.
+//
+// There is one final mode of use, where a renderer spontaneously decides to
+// transmit a collection of histogram data. This is designed for use when the
+// renderer is terminating. Unfortunately, renders may be terminated without
+// warning, and the best we can do is periodically acquire data from a tab, such
+// as when a page load has completed. In this mode, the renderer uses a
+// reserved sequence number, different from any sequence number that might be
+// specified by a browser request. Since this sequence number can't match an
+// outstanding sequence number, the pickled data is accepted into the browser,
+// but there is no impact on the counters.
+
+class HistogramSynchronizer : public content::HistogramSubscriber {
+ public:
+ enum ProcessHistogramRequester {
+ UNKNOWN,
+ ASYNC_HISTOGRAMS,
+ };
+
+ // Return pointer to the singleton instance for the current process, or NULL
+ // if none.
+ static HistogramSynchronizer* GetInstance();
+
+ // Contact all processes, and get them to upload to the browser any/all
+ // changes to histograms. This method is called from about:histograms.
+ static void FetchHistograms();
+
+ // Contact all child processes, and get them to upload to the browser any/all
+ // changes to histograms. When all changes have been acquired, or when the
+ // wait time expires (whichever is sooner), post the callback to the
+ // specified message loop. Note the callback is posted exactly once.
+ static void FetchHistogramsAsynchronously(MessageLoop* callback_thread,
+ const base::Closure& callback,
+ base::TimeDelta wait_time);
+
+ private:
+ friend struct DefaultSingletonTraits<HistogramSynchronizer>;
+
+ class RequestContext;
+
+ HistogramSynchronizer();
+ virtual ~HistogramSynchronizer();
+
+ // Establish a new sequence number, and use it to notify all processes
+ // (renderers, plugins, GPU, etc) of the need to supply, to the browser,
+ // any/all changes to their histograms. |wait_time| specifies the amount of
+ // time to wait before cancelling the requests for non-responsive processes.
+ void RegisterAndNotifyAllProcesses(ProcessHistogramRequester requester,
+ base::TimeDelta wait_time);
+
+ // -------------------------------------------------------
+ // HistogramSubscriber methods for browser child processes
+ // -------------------------------------------------------
+
+ // Update the number of pending processes for the given |sequence_number|.
+ // This is called on UI thread.
+ virtual void OnPendingProcesses(int sequence_number,
+ int pending_processes,
+ bool end) OVERRIDE;
+
+ // Send histogram_data back to caller and also record that we are waiting
+ // for one less histogram data from child process for the given sequence
+ // number. This method is accessible on UI thread.
+ virtual void OnHistogramDataCollected(
+ int sequence_number,
+ const std::vector<std::string>& pickled_histograms) OVERRIDE;
+
+ // Set the callback_thread_ and callback_ members. If these members already
+ // had values, then as a side effect, post the old callback_ to the old
+ // callaback_thread_. This side effect should not generally happen, but is in
+ // place to assure correctness (that any tasks that were set, are eventually
+ // called, and never merely discarded).
+ void SetCallbackTaskAndThread(MessageLoop* callback_thread,
+ const base::Closure& callback);
+
+ void ForceHistogramSynchronizationDoneCallback(int sequence_number);
+
+ // Internal helper function, to post task, and record callback stats.
+ void InternalPostTask(MessageLoop* thread, const base::Closure& callback);
+
+ // Gets a new sequence number to be sent to processes from browser process.
+ int GetNextAvailableSequenceNumber(ProcessHistogramRequester requster);
+
+ // This lock_ protects access to all members.
+ base::Lock lock_;
+
+ // When a request is made to asynchronously update the histograms, we store
+ // the task and thread we use to post a completion notification in
+ // callback_ and callback_thread_.
+ base::Closure callback_;
+ MessageLoop* callback_thread_;
+
+ // We don't track the actual processes that are contacted for an update, only
+ // the count of the number of processes, and we can sometimes time-out and
+ // give up on a "slow to respond" process. We use a sequence_number to be
+ // sure a response from a process is associated with the current round of
+ // requests (and not merely a VERY belated prior response).
+ // All sequence numbers used are non-negative.
+ // last_used_sequence_number_ is the most recently used number (used to avoid
+ // reuse for a long time).
+ int last_used_sequence_number_;
+
+ // The sequence number used by the most recent asynchronous update request to
+ // contact all processes.
+ int async_sequence_number_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index bfea883..1531d1abb 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -54,6 +54,7 @@
#include "content/browser/geolocation/geolocation_dispatcher_host.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/browser/histogram_message_filter.h"
#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
#include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h"
#include "content/browser/mime_registry_message_filter.h"
@@ -603,6 +604,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetContentClient()->browser()->CreateQuotaPermissionContext()));
channel_->AddFilter(new GamepadBrowserMessageFilter(this));
channel_->AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
+ channel_->AddFilter(new content::HistogramMessageFilter());
}
int RenderProcessHostImpl::GetNextRoutingID() {
diff --git a/content/browser/resource_context_impl.cc b/content/browser/resource_context_impl.cc
index ef9b75d..2a143f1 100644
--- a/content/browser/resource_context_impl.cc
+++ b/content/browser/resource_context_impl.cc
@@ -8,6 +8,7 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/browser/histogram_internals_request_job.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
#include "content/browser/net/view_blob_internals_job_factory.h"
@@ -119,6 +120,12 @@ class DeveloperProtocolHandler
}
#endif
+ // Next check for chrome://histograms/, which uses its own job type.
+ if (request->url().SchemeIs(chrome::kChromeUIScheme) &&
+ request->url().host() == chrome::kChromeUIHistogramHost) {
+ return new HistogramInternalsRequestJob(request);
+ }
+
return NULL;
}
diff --git a/content/common/child_histogram_message_filter.cc b/content/common/child_histogram_message_filter.cc
new file mode 100644
index 0000000..5cc137c
--- /dev/null
+++ b/content/common/child_histogram_message_filter.cc
@@ -0,0 +1,98 @@
+// 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.
+
+#include "content/common/child_histogram_message_filter.h"
+
+#include <ctype.h>
+
+#include "base/bind.h"
+#include "base/message_loop.h"
+#include "content/common/child_process.h"
+#include "content/common/child_process_messages.h"
+#include "content/common/child_thread.h"
+
+namespace content {
+
+ChildHistogramMessageFilter::ChildHistogramMessageFilter()
+ : channel_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(histogram_snapshot_manager_(this)) {
+}
+
+ChildHistogramMessageFilter::~ChildHistogramMessageFilter() {
+}
+
+void ChildHistogramMessageFilter::OnFilterAdded(IPC::Channel* channel) {
+ channel_ = channel;
+}
+
+void ChildHistogramMessageFilter::OnFilterRemoved() {
+}
+
+bool ChildHistogramMessageFilter::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ChildHistogramMessageFilter, message)
+ IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildHistogramData,
+ OnGetChildHistogramData)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ChildHistogramMessageFilter::SendHistograms(int sequence_number) {
+ ChildProcess::current()->io_message_loop_proxy()->PostTask(
+ FROM_HERE, base::Bind(&ChildHistogramMessageFilter::UploadAllHistrograms,
+ this, sequence_number));
+}
+
+void ChildHistogramMessageFilter::OnGetChildHistogramData(int sequence_number) {
+ UploadAllHistrograms(sequence_number);
+}
+
+void ChildHistogramMessageFilter::UploadAllHistrograms(int sequence_number) {
+ DCHECK_EQ(0u, pickled_histograms_.size());
+
+ base::StatisticsRecorder::CollectHistogramStats("ChildProcess");
+
+ // Push snapshots into our pickled_histograms_ vector.
+ histogram_snapshot_manager_.PrepareDeltas(
+ base::Histogram::kIPCSerializationSourceFlag, false);
+
+ channel_->Send(new ChildProcessHostMsg_ChildHistogramData(
+ sequence_number, pickled_histograms_));
+
+ pickled_histograms_.clear();
+ static int count = 0;
+ count++;
+ DHISTOGRAM_COUNTS("Histogram.ChildProcessHistogramSentCount", count);
+}
+
+void ChildHistogramMessageFilter::RecordDelta(
+ const base::Histogram& histogram,
+ const base::Histogram::SampleSet& snapshot) {
+ DCHECK_NE(0, snapshot.TotalCount());
+ snapshot.CheckSize(histogram);
+
+ std::string histogram_info =
+ base::Histogram::SerializeHistogramInfo(histogram, snapshot);
+
+ pickled_histograms_.push_back(histogram_info);
+}
+
+void ChildHistogramMessageFilter::InconsistencyDetected(int problem) {
+ UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesChildProcess",
+ problem, base::Histogram::NEVER_EXCEEDED_VALUE);
+}
+
+void ChildHistogramMessageFilter::UniqueInconsistencyDetected(int problem) {
+ UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesChildProcessUnique",
+ problem, base::Histogram::NEVER_EXCEEDED_VALUE);
+}
+
+void ChildHistogramMessageFilter::SnapshotProblemResolved(int amount) {
+ UMA_HISTOGRAM_COUNTS("Histogram.InconsistentSnapshotChildProcess",
+ std::abs(amount));
+}
+
+} // namespace content
diff --git a/content/common/child_histogram_message_filter.h b/content/common/child_histogram_message_filter.h
new file mode 100644
index 0000000..ce9a348
--- /dev/null
+++ b/content/common/child_histogram_message_filter.h
@@ -0,0 +1,65 @@
+// 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.
+
+#ifndef CONTENT_COMMOM_CHILD_HISTOGRAM_MESSAGE_FILTER_H_
+#define CONTENT_COMMOM_CHILD_HISTOGRAM_MESSAGE_FILTER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_flattener.h"
+#include "base/metrics/histogram_snapshot_manager.h"
+#include "ipc/ipc_channel_proxy.h"
+
+class MessageLoop;
+
+namespace content {
+
+class ChildHistogramMessageFilter : public base::HistogramFlattener,
+ public IPC::ChannelProxy::MessageFilter {
+ public:
+ ChildHistogramMessageFilter();
+
+ // IPC::ChannelProxy::MessageFilter implementation.
+ virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
+ virtual void OnFilterRemoved() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ void SendHistograms(int sequence_number);
+
+ // HistogramFlattener interface (override) methods.
+ virtual void RecordDelta(const base::Histogram& histogram,
+ const base::Histogram::SampleSet& snapshot) OVERRIDE;
+ virtual void InconsistencyDetected(int problem) OVERRIDE;
+ virtual void UniqueInconsistencyDetected(int problem) OVERRIDE;
+ virtual void SnapshotProblemResolved(int amount) OVERRIDE;
+
+ private:
+ typedef std::vector<std::string> HistogramPickledList;
+
+ virtual ~ChildHistogramMessageFilter();
+
+ // Message handlers.
+ virtual void OnGetChildHistogramData(int sequence_number);
+
+ // Extract snapshot data and then send it off the the Browser process.
+ // Send only a delta to what we have already sent.
+ void UploadAllHistrograms(int sequence_number);
+
+ IPC::Channel* channel_;
+
+ // Collection of histograms to send to the browser.
+ HistogramPickledList pickled_histograms_;
+
+ // |histogram_snapshot_manager_| prepares histogram deltas for transmission.
+ base::HistogramSnapshotManager histogram_snapshot_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildHistogramMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMOM_CHILD_HISTOGRAM_MESSAGE_FILTER_H_
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h
index a48067b..1403969 100644
--- a/content/common/child_process_messages.h
+++ b/content/common/child_process_messages.h
@@ -5,6 +5,9 @@
// Common IPC messages used for child processes.
// Multiply-included message file, hence no include guard.
+#include <string>
+#include <vector>
+
#include "base/shared_memory.h"
#include "base/tracked_objects.h"
#include "base/values.h"
@@ -87,7 +90,11 @@ IPC_MESSAGE_CONTROL1(ChildProcessMsg_SetProfilerStatus,
// Send to all the child processes to send back profiler data (ThreadData in
// tracked_objects).
IPC_MESSAGE_CONTROL1(ChildProcessMsg_GetChildProfilerData,
- int /* sequence number */)
+ int /* sequence_number */)
+
+// Send to all the child processes to send back histogram data.
+IPC_MESSAGE_CONTROL1(ChildProcessMsg_GetChildHistogramData,
+ int /* sequence_number */)
// Sent to child processes to dump their handle table.
IPC_MESSAGE_CONTROL0(ChildProcessMsg_DumpHandles)
@@ -122,8 +129,13 @@ IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TraceBufferPercentFullReply,
// Send back profiler data (ThreadData in tracked_objects).
IPC_MESSAGE_CONTROL2(ChildProcessHostMsg_ChildProfilerData,
- int, /* sequence number */
- tracked_objects::ProcessDataSnapshot /* profiler data */)
+ int, /* sequence_number */
+ tracked_objects::ProcessDataSnapshot /* profiler_data */)
+
+// Send back histograms as vector of pickled-histogram strings.
+IPC_MESSAGE_CONTROL2(ChildProcessHostMsg_ChildHistogramData,
+ int, /* sequence_number */
+ std::vector<std::string> /* histogram_data */)
// Reply to ChildProcessMsg_DumpHandles when handle table dump is complete.
IPC_MESSAGE_CONTROL0(ChildProcessHostMsg_DumpHandlesDone)
diff --git a/content/common/child_thread.cc b/content/common/child_thread.cc
index e313345..7dec3ec 100644
--- a/content/common/child_thread.cc
+++ b/content/common/child_thread.cc
@@ -10,6 +10,7 @@
#include "base/process.h"
#include "base/string_util.h"
#include "base/tracked_objects.h"
+#include "content/common/child_histogram_message_filter.h"
#include "content/common/child_process.h"
#include "content/common/child_process_messages.h"
#include "content/common/child_trace_message_filter.h"
@@ -60,6 +61,9 @@ void ChildThread::Init() {
sync_message_filter_ =
new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent());
+ histogram_message_filter_ = new content::ChildHistogramMessageFilter();
+
+ channel_->AddFilter(histogram_message_filter_.get());
channel_->AddFilter(sync_message_filter_.get());
channel_->AddFilter(new ChildTraceMessageFilter());
}
@@ -69,6 +73,7 @@ ChildThread::~ChildThread() {
IPC::Logging::GetInstance()->SetIPCSender(NULL);
#endif
+ channel_->RemoveFilter(histogram_message_filter_.get());
channel_->RemoveFilter(sync_message_filter_.get());
// The ChannelProxy object caches a pointer to the IPC thread, so need to
diff --git a/content/common/child_thread.h b/content/common/child_thread.h
index 1a583de..22cfb2c 100644
--- a/content/common/child_thread.h
+++ b/content/common/child_thread.h
@@ -20,6 +20,7 @@ class QuotaDispatcher;
class SocketStreamDispatcher;
namespace content {
+class ChildHistogramMessageFilter;
class ResourceDispatcher;
}
@@ -81,6 +82,10 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
// lifetime is less than the main thread.
IPC::SyncMessageFilter* sync_message_filter();
+ content::ChildHistogramMessageFilter* child_histogram_message_filter() const {
+ return histogram_message_filter_.get();
+ }
+
MessageLoop* message_loop();
// Returns the one child thread.
@@ -146,6 +151,8 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
scoped_ptr<QuotaDispatcher> quota_dispatcher_;
+ scoped_refptr<content::ChildHistogramMessageFilter> histogram_message_filter_;
+
DISALLOW_COPY_AND_ASSIGN(ChildThread);
};
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 07def56..54115b9 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -84,6 +84,7 @@
'public/browser/global_request_id.h',
'public/browser/gpu_data_manager.h',
'public/browser/gpu_data_manager_observer.h',
+ 'public/browser/histogram_fetcher.h',
'public/browser/host_zoom_map.h',
'public/browser/indexed_db_context.h',
'public/browser/interstitial_page.h',
@@ -406,6 +407,15 @@
'browser/gpu/gpu_process_host_ui_shim.h',
'browser/gpu/gpu_surface_tracker.cc',
'browser/gpu/gpu_surface_tracker.h',
+ 'browser/histogram_controller.cc',
+ 'browser/histogram_controller.h',
+ 'browser/histogram_internals_request_job.cc',
+ 'browser/histogram_internals_request_job.h',
+ 'browser/histogram_message_filter.cc',
+ 'browser/histogram_message_filter.h',
+ 'browser/histogram_subscriber.h',
+ 'browser/histogram_synchronizer.cc',
+ 'browser/histogram_synchronizer.h',
'browser/host_zoom_map_impl.cc',
'browser/host_zoom_map_impl.h',
'browser/in_process_webkit/browser_webkitplatformsupport_impl.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index ae14818..2dbfa9b 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -122,6 +122,8 @@
'common/appcache/appcache_dispatcher.h',
'common/appcache_messages.h',
'common/browser_plugin_messages.h',
+ 'common/child_histogram_message_filter.cc',
+ 'common/child_histogram_message_filter.h',
'common/child_process.cc',
'common/child_process.h',
'common/child_process_host_impl.cc',
diff --git a/content/public/browser/histogram_fetcher.h b/content/public/browser/histogram_fetcher.h
new file mode 100644
index 0000000..73dabde
--- /dev/null
+++ b/content/public/browser/histogram_fetcher.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef CONTENT_PUBLIC_BROWSER_HISTOGRAM_FETCHER_H_
+#define CONTENT_PUBLIC_BROWSER_HISTOGRAM_FETCHER_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/time.h"
+#include "content/common/content_export.h"
+
+class MessageLoop;
+
+namespace content {
+
+// Fetch histogram data asynchronously from the various child processes, into
+// the browser process. This method is used by the metrics services in
+// preparation for a log upload. It contacts all processes, and get them to
+// upload to the browser any/all changes to histograms. When all changes have
+// been acquired, or when the wait time expires (whichever is sooner), post the
+// callback to the specified message loop. Note the callback is posted exactly
+// once.
+CONTENT_EXPORT void FetchHistogramsAsynchronously(MessageLoop* callback_thread,
+ const base::Closure& callback,
+ base::TimeDelta wait_time);
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_HISTOGRAM_FETCHER_H_
diff --git a/content/public/common/content_constants.cc b/content/public/common/content_constants.cc
index 7875162..f3b79f59f 100644
--- a/content/public/common/content_constants.cc
+++ b/content/public/common/content_constants.cc
@@ -30,4 +30,6 @@ const char kStatsFilename[] = "ChromiumStats2";
const int kStatsMaxThreads = 32;
const int kStatsMaxCounters = 3000;
+const int kHistogramSynchronizerReservedSequenceNumber = 0;
+
} // namespace content
diff --git a/content/public/common/content_constants.h b/content/public/common/content_constants.h
index e0bc5f4..3b1c091 100644
--- a/content/public/common/content_constants.h
+++ b/content/public/common/content_constants.h
@@ -46,6 +46,13 @@ extern const char kStatsFilename[];
extern const int kStatsMaxThreads;
extern const int kStatsMaxCounters;
+// Most sequence numbers are used by a renderer when responding to a browser
+// request for histogram data. This reserved number is used when a renderer
+// sends an unprovoked update, such as after a page has been loaded. Using
+// this reserved constant avoids any chance of confusion with a response having
+// a browser-supplied sequence number.
+CONTENT_EXPORT extern const int kHistogramSynchronizerReservedSequenceNumber;
+
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_CONTENT_CONSTANTS_H_
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index 85c3ead..8337146 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -35,6 +35,7 @@ const char kChromeUIBlobInternalsHost[] = "blob-internals";
const char kChromeUIBrowserCrashHost[] = "inducebrowsercrashforrealz";
const char kChromeUINetworkViewCacheHost[] = "view-http-cache";
const char kChromeUITcmallocHost[] = "tcmalloc";
+const char kChromeUIHistogramHost[] = "histograms";
const char kChromeUICrashURL[] = "chrome://crash";
const char kChromeUIGpuCleanURL[] = "chrome://gpuclean";
const char kChromeUIGpuCrashURL[] = "chrome://gpucrash";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index 919685c..7fd1150 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -41,6 +41,7 @@ CONTENT_EXPORT extern const char kChromeUIBlobInternalsHost[];
CONTENT_EXPORT extern const char kChromeUIBrowserCrashHost[];
CONTENT_EXPORT extern const char kChromeUINetworkViewCacheHost[];
CONTENT_EXPORT extern const char kChromeUITcmallocHost[];
+CONTENT_EXPORT extern const char kChromeUIHistogramHost[];
// Full about URLs (including schemes).
CONTENT_EXPORT extern const char kChromeUICrashURL[];
diff --git a/content/public/renderer/render_thread.h b/content/public/renderer/render_thread.h
index 1c10084..fd2fa36 100644
--- a/content/public/renderer/render_thread.h
+++ b/content/public/renderer/render_thread.h
@@ -104,6 +104,8 @@ class CONTENT_EXPORT RenderThread : public IPC::Sender {
virtual void SetIdleNotificationDelayInMs(
int64 idle_notification_delay_in_ms) = 0;
+ virtual void UpdateHistograms(int sequence_number) = 0;
+
#if defined(OS_WIN)
// Request that the given font be loaded by the browser so it's cached by the
// OS. Please see ChildProcessHost::PreCacheFont for details.
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index f7fec7b..3a68a31 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -73,6 +73,7 @@ class MockRenderThread : public RenderThread {
virtual void PreCacheFont(const LOGFONT& log_font) OVERRIDE;
virtual void ReleaseCachedFonts() OVERRIDE;
#endif
+ virtual void UpdateHistograms(int sequence_number) OVERRIDE;
//////////////////////////////////////////////////////////////////////////
// The following functions are called by the test itself.
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index afbf45f..dea6cf5 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -25,6 +25,7 @@
#include "base/values.h"
#include "base/win/scoped_com_initializer.h"
#include "content/common/appcache/appcache_dispatcher.h"
+#include "content/common/child_histogram_message_filter.h"
#include "content/common/child_process_messages.h"
#include "content/common/database_messages.h"
#include "content/common/db_message_filter.h"
@@ -759,6 +760,10 @@ void RenderThreadImpl::ReleaseCachedFonts() {
#endif // OS_WIN
+void RenderThreadImpl::UpdateHistograms(int sequence_number) {
+ child_histogram_message_filter()->SendHistograms(sequence_number);
+}
+
bool RenderThreadImpl::IsWebFrameValid(WebKit::WebFrame* web_frame) {
if (!web_frame)
return false; // We must be shutting down.
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 381581f..8857120 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -129,6 +129,7 @@ class CONTENT_EXPORT RenderThreadImpl : public content::RenderThread,
virtual void PreCacheFont(const LOGFONT& log_font) OVERRIDE;
virtual void ReleaseCachedFonts() OVERRIDE;
#endif
+ virtual void UpdateHistograms(int sequence_number) OVERRIDE;
// content::ChildThread:
virtual bool IsWebFrameValid(WebKit::WebFrame* frame) OVERRIDE;
diff --git a/content/test/mock_render_thread.cc b/content/test/mock_render_thread.cc
index 8143718..c333b07 100644
--- a/content/test/mock_render_thread.cc
+++ b/content/test/mock_render_thread.cc
@@ -174,6 +174,9 @@ void MockRenderThread::ReleaseCachedFonts() {
#endif // OS_WIN
+void MockRenderThread::UpdateHistograms(int sequence_number) {
+}
+
void MockRenderThread::SendCloseMessage() {
ViewMsg_Close msg(routing_id_);
widget_->OnMessageReceived(msg);