Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: chrome/browser/metrics/metrics_service.cc

Issue 289283011: Introduce ChromeStabilityMetricsProvider (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/metrics/metrics_service.h ('k') | chrome/browser/metrics/thread_watcher.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 //------------------------------------------------------------------------------ 5 //------------------------------------------------------------------------------
6 // Description of the life cycle of a instance of MetricsService. 6 // Description of the life cycle of a instance of MetricsService.
7 // 7 //
8 // OVERVIEW 8 // OVERVIEW
9 // 9 //
10 // A MetricsService instance is typically created at application startup. It is 10 // A MetricsService instance is typically created at application startup. It is
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 #include "base/strings/string_number_conversions.h" 179 #include "base/strings/string_number_conversions.h"
180 #include "base/strings/utf_string_conversions.h" 180 #include "base/strings/utf_string_conversions.h"
181 #include "base/threading/platform_thread.h" 181 #include "base/threading/platform_thread.h"
182 #include "base/threading/thread.h" 182 #include "base/threading/thread.h"
183 #include "base/threading/thread_restrictions.h" 183 #include "base/threading/thread_restrictions.h"
184 #include "base/tracked_objects.h" 184 #include "base/tracked_objects.h"
185 #include "base/values.h" 185 #include "base/values.h"
186 #include "chrome/browser/browser_process.h" 186 #include "chrome/browser/browser_process.h"
187 #include "chrome/browser/chrome_notification_types.h" 187 #include "chrome/browser/chrome_notification_types.h"
188 #include "chrome/browser/io_thread.h" 188 #include "chrome/browser/io_thread.h"
189 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
189 #include "chrome/browser/metrics/compression_utils.h" 190 #include "chrome/browser/metrics/compression_utils.h"
190 #include "chrome/browser/metrics/metrics_log.h" 191 #include "chrome/browser/metrics/metrics_log.h"
191 #include "chrome/browser/metrics/metrics_state_manager.h" 192 #include "chrome/browser/metrics/metrics_state_manager.h"
192 #include "chrome/browser/metrics/network_metrics_provider.h" 193 #include "chrome/browser/metrics/network_metrics_provider.h"
193 #include "chrome/browser/metrics/omnibox_metrics_provider.h" 194 #include "chrome/browser/metrics/omnibox_metrics_provider.h"
194 #include "chrome/browser/metrics/tracking_synchronizer.h" 195 #include "chrome/browser/metrics/tracking_synchronizer.h"
195 #include "chrome/browser/ui/browser_otr_state.h" 196 #include "chrome/browser/ui/browser_otr_state.h"
196 #include "chrome/common/chrome_constants.h" 197 #include "chrome/common/chrome_constants.h"
197 #include "chrome/common/chrome_switches.h" 198 #include "chrome/common/chrome_switches.h"
198 #include "chrome/common/crash_keys.h" 199 #include "chrome/common/crash_keys.h"
199 #include "chrome/common/pref_names.h" 200 #include "chrome/common/pref_names.h"
200 #include "chrome/common/variations/variations_util.h" 201 #include "chrome/common/variations/variations_util.h"
201 #include "components/metrics/metrics_log_base.h" 202 #include "components/metrics/metrics_log_base.h"
202 #include "components/metrics/metrics_log_manager.h" 203 #include "components/metrics/metrics_log_manager.h"
203 #include "components/metrics/metrics_pref_names.h" 204 #include "components/metrics/metrics_pref_names.h"
204 #include "components/metrics/metrics_reporting_scheduler.h" 205 #include "components/metrics/metrics_reporting_scheduler.h"
205 #include "components/metrics/metrics_service_client.h" 206 #include "components/metrics/metrics_service_client.h"
206 #include "components/variations/entropy_provider.h" 207 #include "components/variations/entropy_provider.h"
207 #include "components/variations/metrics_util.h" 208 #include "components/variations/metrics_util.h"
208 #include "content/public/browser/child_process_data.h" 209 #include "content/public/browser/child_process_data.h"
209 #include "content/public/browser/load_notification_details.h"
210 #include "content/public/browser/notification_service.h"
211 #include "content/public/browser/plugin_service.h" 210 #include "content/public/browser/plugin_service.h"
212 #include "content/public/browser/render_process_host.h" 211 #include "content/public/browser/render_process_host.h"
213 #include "content/public/browser/user_metrics.h" 212 #include "content/public/browser/user_metrics.h"
214 #include "content/public/browser/web_contents.h"
215 #include "content/public/common/process_type.h" 213 #include "content/public/common/process_type.h"
216 #include "content/public/common/webplugininfo.h" 214 #include "content/public/common/webplugininfo.h"
217 #include "extensions/browser/process_map.h"
218 #include "net/base/load_flags.h" 215 #include "net/base/load_flags.h"
219 #include "net/url_request/url_fetcher.h" 216 #include "net/url_request/url_fetcher.h"
220 217
221 #if defined(OS_CHROMEOS) 218 #if defined(OS_CHROMEOS)
222 #include "chrome/browser/chromeos/settings/cros_settings.h" 219 #include "chrome/browser/chromeos/settings/cros_settings.h"
223 #include "chromeos/system/statistics_provider.h" 220 #include "chromeos/system/statistics_provider.h"
224 #endif 221 #endif
225 222
226 #if defined(OS_WIN) 223 #if defined(OS_WIN)
227 #include <windows.h> // Needed for STATUS_* codes 224 #include <windows.h> // Needed for STATUS_* codes
228 #include "base/win/registry.h" 225 #include "base/win/registry.h"
229 #include "chrome/browser/metrics/google_update_metrics_provider_win.h" 226 #include "chrome/browser/metrics/google_update_metrics_provider_win.h"
230 #endif 227 #endif
231 228
232 #if defined(OS_ANDROID) 229 #if defined(OS_ANDROID)
233 // TODO(asvitkine): Move this out of MetricsService. 230 // TODO(asvitkine): Move this out of MetricsService.
234 #include "chrome/browser/metrics/android_metrics_provider.h" 231 #include "chrome/browser/metrics/android_metrics_provider.h"
235 #endif 232 #endif
236 233
237 using base::Time; 234 using base::Time;
238 using content::BrowserThread; 235 using content::BrowserThread;
239 using content::ChildProcessData; 236 using content::ChildProcessData;
240 using content::LoadNotificationDetails;
241 using content::PluginService; 237 using content::PluginService;
242 using metrics::MetricsLogManager; 238 using metrics::MetricsLogManager;
243 239
244 namespace { 240 namespace {
245 241
246 // Check to see that we're being called on only one thread. 242 // Check to see that we're being called on only one thread.
247 bool IsSingleThreaded() { 243 bool IsSingleThreaded() {
248 static base::PlatformThreadId thread_id = 0; 244 static base::PlatformThreadId thread_id = 0;
249 if (!thread_id) 245 if (!thread_id)
250 thread_id = base::PlatformThread::CurrentId(); 246 thread_id = base::PlatformThread::CurrentId();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 return SUCCESS; 291 return SUCCESS;
296 case 400: 292 case 400:
297 return BAD_REQUEST; 293 return BAD_REQUEST;
298 case net::URLFetcher::RESPONSE_CODE_INVALID: 294 case net::URLFetcher::RESPONSE_CODE_INVALID:
299 return NO_RESPONSE; 295 return NO_RESPONSE;
300 default: 296 default:
301 return UNKNOWN_FAILURE; 297 return UNKNOWN_FAILURE;
302 } 298 }
303 } 299 }
304 300
305 // Converts an exit code into something that can be inserted into our
306 // histograms (which expect non-negative numbers less than MAX_INT).
307 int MapCrashExitCodeForHistogram(int exit_code) {
308 #if defined(OS_WIN)
309 // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in
310 // histograms.cc. Solve this by remapping it to a smaller value, which
311 // hopefully doesn't conflict with other codes.
312 if (exit_code == STATUS_GUARD_PAGE_VIOLATION)
313 return 0x1FCF7EC3; // Randomly picked number.
314 #endif
315
316 return std::abs(exit_code);
317 }
318
319 void MarkAppCleanShutdownAndCommit() { 301 void MarkAppCleanShutdownAndCommit() {
320 PrefService* pref = g_browser_process->local_state(); 302 PrefService* pref = g_browser_process->local_state();
321 pref->SetBoolean(prefs::kStabilityExitedCleanly, true); 303 pref->SetBoolean(prefs::kStabilityExitedCleanly, true);
322 pref->SetInteger(prefs::kStabilityExecutionPhase, 304 pref->SetInteger(prefs::kStabilityExecutionPhase,
323 MetricsService::SHUTDOWN_COMPLETE); 305 MetricsService::SHUTDOWN_COMPLETE);
324 // Start writing right away (write happens on a different thread). 306 // Start writing right away (write happens on a different thread).
325 pref->CommitPendingWrite(); 307 pref->CommitPendingWrite();
326 } 308 }
327 309
328 } // namespace 310 } // namespace
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 RegisterMetricsProvider( 447 RegisterMetricsProvider(
466 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider( 448 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider(
467 g_browser_process->local_state()))); 449 g_browser_process->local_state())));
468 #endif // defined(OS_ANDROID) 450 #endif // defined(OS_ANDROID)
469 451
470 // TODO(asvitkine): Move these out of MetricsService. 452 // TODO(asvitkine): Move these out of MetricsService.
471 RegisterMetricsProvider( 453 RegisterMetricsProvider(
472 scoped_ptr<metrics::MetricsProvider>(new NetworkMetricsProvider)); 454 scoped_ptr<metrics::MetricsProvider>(new NetworkMetricsProvider));
473 RegisterMetricsProvider( 455 RegisterMetricsProvider(
474 scoped_ptr<metrics::MetricsProvider>(new OmniboxMetricsProvider)); 456 scoped_ptr<metrics::MetricsProvider>(new OmniboxMetricsProvider));
457 RegisterMetricsProvider(
458 scoped_ptr<metrics::MetricsProvider>(new ChromeStabilityMetricsProvider));
475 459
476 #if defined(OS_WIN) 460 #if defined(OS_WIN)
477 google_update_metrics_provider_ = new GoogleUpdateMetricsProviderWin; 461 google_update_metrics_provider_ = new GoogleUpdateMetricsProviderWin;
478 RegisterMetricsProvider(scoped_ptr<metrics::MetricsProvider>( 462 RegisterMetricsProvider(scoped_ptr<metrics::MetricsProvider>(
479 google_update_metrics_provider_)); 463 google_update_metrics_provider_));
480 #endif 464 #endif
481 BrowserChildProcessObserver::Add(this); 465 BrowserChildProcessObserver::Add(this);
482 } 466 }
483 467
484 MetricsService::~MetricsService() { 468 MetricsService::~MetricsService() {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 recording_active_ = true; 534 recording_active_ = true;
551 535
552 state_manager_->ForceClientIdCreation(); 536 state_manager_->ForceClientIdCreation();
553 crash_keys::SetClientID(state_manager_->client_id()); 537 crash_keys::SetClientID(state_manager_->client_id());
554 if (!log_manager_.current_log()) 538 if (!log_manager_.current_log())
555 OpenNewLog(); 539 OpenNewLog();
556 540
557 for (size_t i = 0; i < metrics_providers_.size(); ++i) 541 for (size_t i = 0; i < metrics_providers_.size(); ++i)
558 metrics_providers_[i]->OnRecordingEnabled(); 542 metrics_providers_[i]->OnRecordingEnabled();
559 543
560 SetUpNotifications(&registrar_, this);
561 base::RemoveActionCallback(action_callback_); 544 base::RemoveActionCallback(action_callback_);
562 action_callback_ = base::Bind(&MetricsService::OnUserAction, 545 action_callback_ = base::Bind(&MetricsService::OnUserAction,
563 base::Unretained(this)); 546 base::Unretained(this));
564 base::AddActionCallback(action_callback_); 547 base::AddActionCallback(action_callback_);
565 } 548 }
566 549
567 void MetricsService::DisableRecording() { 550 void MetricsService::DisableRecording() {
568 DCHECK(IsSingleThreaded()); 551 DCHECK(IsSingleThreaded());
569 552
570 if (!recording_active_) 553 if (!recording_active_)
571 return; 554 return;
572 recording_active_ = false; 555 recording_active_ = false;
573 556
574 base::RemoveActionCallback(action_callback_); 557 base::RemoveActionCallback(action_callback_);
575 registrar_.RemoveAll();
576 558
577 for (size_t i = 0; i < metrics_providers_.size(); ++i) 559 for (size_t i = 0; i < metrics_providers_.size(); ++i)
578 metrics_providers_[i]->OnRecordingDisabled(); 560 metrics_providers_[i]->OnRecordingDisabled();
579 561
580 PushPendingLogsToPersistentStorage(); 562 PushPendingLogsToPersistentStorage();
581 DCHECK(!log_manager_.has_staged_log()); 563 DCHECK(!log_manager_.has_staged_log());
582 } 564 }
583 565
584 bool MetricsService::recording_active() const { 566 bool MetricsService::recording_active() const {
585 DCHECK(IsSingleThreaded()); 567 DCHECK(IsSingleThreaded());
586 return recording_active_; 568 return recording_active_;
587 } 569 }
588 570
589 bool MetricsService::reporting_active() const { 571 bool MetricsService::reporting_active() const {
590 DCHECK(IsSingleThreaded()); 572 DCHECK(IsSingleThreaded());
591 return reporting_active_; 573 return reporting_active_;
592 } 574 }
593 575
594 // static
595 void MetricsService::SetUpNotifications(
596 content::NotificationRegistrar* registrar,
597 content::NotificationObserver* observer) {
598 registrar->Add(observer, content::NOTIFICATION_LOAD_START,
599 content::NotificationService::AllSources());
600 registrar->Add(observer, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
601 content::NotificationService::AllSources());
602 registrar->Add(observer, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
603 content::NotificationService::AllSources());
604 }
605
606 void MetricsService::RecordDelta(const base::HistogramBase& histogram, 576 void MetricsService::RecordDelta(const base::HistogramBase& histogram,
607 const base::HistogramSamples& snapshot) { 577 const base::HistogramSamples& snapshot) {
608 log_manager_.current_log()->RecordHistogramDelta(histogram.histogram_name(), 578 log_manager_.current_log()->RecordHistogramDelta(histogram.histogram_name(),
609 snapshot); 579 snapshot);
610 } 580 }
611 581
612 void MetricsService::InconsistencyDetected( 582 void MetricsService::InconsistencyDetected(
613 base::HistogramBase::Inconsistency problem) { 583 base::HistogramBase::Inconsistency problem) {
614 UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowser", 584 UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowser",
615 problem, base::HistogramBase::NEVER_EXCEEDED_VALUE); 585 problem, base::HistogramBase::NEVER_EXCEEDED_VALUE);
(...skipping 22 matching lines...) Expand all
638 // a separate UMA metric. 608 // a separate UMA metric.
639 if (!IsPluginProcess(data.process_type)) 609 if (!IsPluginProcess(data.process_type))
640 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount); 610 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
641 } 611 }
642 612
643 void MetricsService::BrowserChildProcessInstanceCreated( 613 void MetricsService::BrowserChildProcessInstanceCreated(
644 const content::ChildProcessData& data) { 614 const content::ChildProcessData& data) {
645 GetChildProcessStats(data).instances++; 615 GetChildProcessStats(data).instances++;
646 } 616 }
647 617
648 void MetricsService::Observe(int type,
649 const content::NotificationSource& source,
650 const content::NotificationDetails& details) {
651 DCHECK(log_manager_.current_log());
652 DCHECK(IsSingleThreaded());
653
654 switch (type) {
655 case content::NOTIFICATION_LOAD_START: {
656 content::NavigationController* controller =
657 content::Source<content::NavigationController>(source).ptr();
658 content::WebContents* web_contents = controller->GetWebContents();
659 LogLoadStarted(web_contents);
660 break;
661 }
662
663 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
664 content::RenderProcessHost::RendererClosedDetails* process_details =
665 content::Details<
666 content::RenderProcessHost::RendererClosedDetails>(
667 details).ptr();
668 content::RenderProcessHost* host =
669 content::Source<content::RenderProcessHost>(source).ptr();
670 LogRendererCrash(
671 host, process_details->status, process_details->exit_code);
672 break;
673 }
674
675 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
676 LogRendererHang();
677 break;
678
679 default:
680 NOTREACHED();
681 }
682 }
683
684 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { 618 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) {
685 // If there wasn't a lot of action, maybe the computer was asleep, in which 619 // If there wasn't a lot of action, maybe the computer was asleep, in which
686 // case, the log transmissions should have stopped. Here we start them up 620 // case, the log transmissions should have stopped. Here we start them up
687 // again. 621 // again.
688 if (!in_idle && idle_since_last_transmission_) 622 if (!in_idle && idle_since_last_transmission_)
689 StartSchedulerIfNecessary(); 623 StartSchedulerIfNecessary();
690 idle_since_last_transmission_ = in_idle; 624 idle_since_last_transmission_ = in_idle;
691 } 625 }
692 626
693 void MetricsService::OnApplicationNotIdle() { 627 void MetricsService::OnApplicationNotIdle() {
(...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 pref->SetInteger(path, value + 1); 1453 pref->SetInteger(path, value + 1);
1520 } 1454 }
1521 1455
1522 void MetricsService::IncrementLongPrefsValue(const char* path) { 1456 void MetricsService::IncrementLongPrefsValue(const char* path) {
1523 PrefService* pref = g_browser_process->local_state(); 1457 PrefService* pref = g_browser_process->local_state();
1524 DCHECK(pref); 1458 DCHECK(pref);
1525 int64 value = pref->GetInt64(path); 1459 int64 value = pref->GetInt64(path);
1526 pref->SetInt64(path, value + 1); 1460 pref->SetInt64(path, value + 1);
1527 } 1461 }
1528 1462
1529 void MetricsService::LogLoadStarted(content::WebContents* web_contents) {
1530 content::RecordAction(base::UserMetricsAction("PageLoad"));
1531 HISTOGRAM_ENUMERATION("Chrome.UmaPageloadCounter", 1, 2);
1532 IncrementPrefValue(prefs::kStabilityPageLoadCount);
1533 IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
1534 // We need to save the prefs, as page load count is a critical stat, and it
1535 // might be lost due to a crash :-(.
1536 }
1537
1538 void MetricsService::LogRendererCrash(content::RenderProcessHost* host,
1539 base::TerminationStatus status,
1540 int exit_code) {
1541 bool was_extension_process =
1542 extensions::ProcessMap::Get(host->GetBrowserContext())
1543 ->Contains(host->GetID());
1544 if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
1545 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
1546 if (was_extension_process) {
1547 IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount);
1548
1549 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Extension",
1550 MapCrashExitCodeForHistogram(exit_code));
1551 } else {
1552 IncrementPrefValue(prefs::kStabilityRendererCrashCount);
1553
1554 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
1555 MapCrashExitCodeForHistogram(exit_code));
1556 }
1557
1558 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
1559 was_extension_process ? 2 : 1);
1560 } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
1561 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
1562 was_extension_process ? 2 : 1);
1563 } else if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
1564 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.DisconnectedAlive",
1565 was_extension_process ? 2 : 1);
1566 }
1567 }
1568
1569 void MetricsService::LogRendererHang() {
1570 IncrementPrefValue(prefs::kStabilityRendererHangCount);
1571 }
1572
1573 bool MetricsService::UmaMetricsProperlyShutdown() { 1463 bool MetricsService::UmaMetricsProperlyShutdown() {
1574 CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN || 1464 CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN ||
1575 clean_shutdown_status_ == NEED_TO_SHUTDOWN); 1465 clean_shutdown_status_ == NEED_TO_SHUTDOWN);
1576 return clean_shutdown_status_ == CLEANLY_SHUTDOWN; 1466 return clean_shutdown_status_ == CLEANLY_SHUTDOWN;
1577 } 1467 }
1578 1468
1579 void MetricsService::RegisterSyntheticFieldTrial( 1469 void MetricsService::RegisterSyntheticFieldTrial(
1580 const SyntheticTrialGroup& trial) { 1470 const SyntheticTrialGroup& trial) {
1581 for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) { 1471 for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) {
1582 if (synthetic_trial_groups_[i].id.name == trial.id.name) { 1472 if (synthetic_trial_groups_[i].id.name == trial.id.name) {
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1802 1692
1803 RecordPluginChanges(pref); 1693 RecordPluginChanges(pref);
1804 } 1694 }
1805 1695
1806 // static 1696 // static
1807 bool MetricsService::IsPluginProcess(int process_type) { 1697 bool MetricsService::IsPluginProcess(int process_type) {
1808 return (process_type == content::PROCESS_TYPE_PLUGIN || 1698 return (process_type == content::PROCESS_TYPE_PLUGIN ||
1809 process_type == content::PROCESS_TYPE_PPAPI_PLUGIN || 1699 process_type == content::PROCESS_TYPE_PPAPI_PLUGIN ||
1810 process_type == content::PROCESS_TYPE_PPAPI_BROKER); 1700 process_type == content::PROCESS_TYPE_PPAPI_BROKER);
1811 } 1701 }
OLDNEW
« no previous file with comments | « chrome/browser/metrics/metrics_service.h ('k') | chrome/browser/metrics/thread_watcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698