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

Side by Side Diff: content/browser/loader/resource_dispatcher_host_impl.cc

Issue 2951643003: Add UMA that periodically logs number of outstanding requests (Closed)
Patch Set: Msec -> Sec and style fix Created 3 years, 6 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
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 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading
6 6
7 #include "content/browser/loader/resource_dispatcher_host_impl.h" 7 #include "content/browser/loader/resource_dispatcher_host_impl.h"
8 8
9 #include <stddef.h> 9 #include <stddef.h>
10 10
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 #include "content/browser/service_worker/service_worker_navigation_handle_core.h " 71 #include "content/browser/service_worker/service_worker_navigation_handle_core.h "
72 #include "content/browser/service_worker/service_worker_request_handler.h" 72 #include "content/browser/service_worker/service_worker_request_handler.h"
73 #include "content/browser/streams/stream.h" 73 #include "content/browser/streams/stream.h"
74 #include "content/browser/streams/stream_context.h" 74 #include "content/browser/streams/stream_context.h"
75 #include "content/browser/streams/stream_registry.h" 75 #include "content/browser/streams/stream_registry.h"
76 #include "content/common/net/url_request_service_worker_data.h" 76 #include "content/common/net/url_request_service_worker_data.h"
77 #include "content/common/resource_messages.h" 77 #include "content/common/resource_messages.h"
78 #include "content/common/resource_request.h" 78 #include "content/common/resource_request.h"
79 #include "content/common/resource_request_body_impl.h" 79 #include "content/common/resource_request_body_impl.h"
80 #include "content/common/resource_request_completion_status.h" 80 #include "content/common/resource_request_completion_status.h"
81 #include "content/common/site_isolation_policy.h"
81 #include "content/common/view_messages.h" 82 #include "content/common/view_messages.h"
82 #include "content/public/browser/browser_thread.h" 83 #include "content/public/browser/browser_thread.h"
83 #include "content/public/browser/global_request_id.h" 84 #include "content/public/browser/global_request_id.h"
84 #include "content/public/browser/navigation_ui_data.h" 85 #include "content/public/browser/navigation_ui_data.h"
85 #include "content/public/browser/plugin_service.h" 86 #include "content/public/browser/plugin_service.h"
86 #include "content/public/browser/resource_dispatcher_host_delegate.h" 87 #include "content/public/browser/resource_dispatcher_host_delegate.h"
87 #include "content/public/browser/resource_request_details.h" 88 #include "content/public/browser/resource_request_details.h"
88 #include "content/public/browser/resource_throttle.h" 89 #include "content/public/browser/resource_throttle.h"
89 #include "content/public/browser/stream_handle.h" 90 #include "content/public/browser/stream_handle.h"
90 #include "content/public/browser/stream_info.h" 91 #include "content/public/browser/stream_info.h"
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 162
162 namespace content { 163 namespace content {
163 164
164 namespace { 165 namespace {
165 166
166 static ResourceDispatcherHostImpl* g_resource_dispatcher_host; 167 static ResourceDispatcherHostImpl* g_resource_dispatcher_host;
167 168
168 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates 169 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates
169 const int kUpdateLoadStatesIntervalMsec = 250; 170 const int kUpdateLoadStatesIntervalMsec = 250;
170 171
172 // The interval for calls to RecordOutstandingRequestsStats.
173 const int kRecordOutstandingRequestsStatsIntervalSec = 60;
174
171 // Maximum byte "cost" of all the outstanding requests for a renderer. 175 // Maximum byte "cost" of all the outstanding requests for a renderer.
172 // See declaration of |max_outstanding_requests_cost_per_process_| for details. 176 // See declaration of |max_outstanding_requests_cost_per_process_| for details.
173 // This bound is 25MB, which allows for around 6000 outstanding requests. 177 // This bound is 25MB, which allows for around 6000 outstanding requests.
174 const int kMaxOutstandingRequestsCostPerProcess = 26214400; 178 const int kMaxOutstandingRequestsCostPerProcess = 26214400;
175 179
176 // The number of milliseconds after noting a user gesture that we will 180 // The number of milliseconds after noting a user gesture that we will
177 // tag newly-created URLRequest objects with the 181 // tag newly-created URLRequest objects with the
178 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary 182 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary
179 // guess at how long to expect direct impact from a user gesture, but 183 // guess at how long to expect direct impact from a user gesture, but
180 // this should be OK as the load flag is a best-effort thing only, 184 // this should be OK as the load flag is a best-effort thing only,
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 g_resource_dispatcher_host = this; 357 g_resource_dispatcher_host = this;
354 358
355 ANNOTATE_BENIGN_RACE( 359 ANNOTATE_BENIGN_RACE(
356 &last_user_gesture_time_, 360 &last_user_gesture_time_,
357 "We don't care about the precise value, see http://crbug.com/92889"); 361 "We don't care about the precise value, see http://crbug.com/92889");
358 362
359 io_thread_task_runner_->PostTask( 363 io_thread_task_runner_->PostTask(
360 FROM_HERE, 364 FROM_HERE,
361 base::Bind(&ResourceDispatcherHostImpl::OnInit, base::Unretained(this))); 365 base::Bind(&ResourceDispatcherHostImpl::OnInit, base::Unretained(this)));
362 366
363 update_load_states_timer_.reset(new base::RepeatingTimer()); 367 update_load_states_timer_ = base::MakeUnique<base::RepeatingTimer>();
368
369 // Monitor per-tab outstanding requests only if OOPIF is not enabled, because
370 // the routing id doesn't represent tabs in OOPIF modes.
371 if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites() &&
372 !SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
373 !SiteIsolationPolicy::AreIsolatedOriginsEnabled()) {
alexmos 2017/06/30 17:27:22 Just saw this CL, and this check seems problematic
374 record_outstanding_requests_stats_timer_ =
375 base::MakeUnique<base::RepeatingTimer>();
376 }
364 } 377 }
365 378
366 // The default ctor is only used by unittests. It is reasonable to assume that 379 // The default ctor is only used by unittests. It is reasonable to assume that
367 // the main thread and the IO thread are the same for unittests. 380 // the main thread and the IO thread are the same for unittests.
368 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() 381 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl()
369 : ResourceDispatcherHostImpl(CreateDownloadHandlerIntercept(), 382 : ResourceDispatcherHostImpl(CreateDownloadHandlerIntercept(),
370 base::ThreadTaskRunnerHandle::Get()) {} 383 base::ThreadTaskRunnerHandle::Get()) {}
371 384
372 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { 385 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() {
373 DCHECK(outstanding_requests_stats_map_.empty()); 386 DCHECK(outstanding_requests_stats_map_.empty());
387 DCHECK(outstanding_requests_per_tab_map_.empty());
374 DCHECK(g_resource_dispatcher_host); 388 DCHECK(g_resource_dispatcher_host);
375 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); 389 DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
376 g_resource_dispatcher_host = NULL; 390 g_resource_dispatcher_host = NULL;
377 } 391 }
378 392
379 // static 393 // static
380 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { 394 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() {
381 return g_resource_dispatcher_host; 395 return g_resource_dispatcher_host;
382 } 396 }
383 397
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 596
583 const net::URLRequestJobFactory* job_factory = 597 const net::URLRequestJobFactory* job_factory =
584 info->GetContext()->GetRequestContext()->job_factory(); 598 info->GetContext()->GetRequestContext()->job_factory();
585 if (!url.is_valid() || job_factory->IsHandledProtocol(url.scheme())) 599 if (!url.is_valid() || job_factory->IsHandledProtocol(url.scheme()))
586 return false; 600 return false;
587 601
588 return delegate_->HandleExternalProtocol(url, info); 602 return delegate_->HandleExternalProtocol(url, info);
589 } 603 }
590 604
591 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { 605 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
592 // Make sure we have the load state monitor running. 606 // Make sure we have the load state monitors running.
593 if (!update_load_states_timer_->IsRunning() && 607 if (!update_load_states_timer_->IsRunning() &&
594 scheduler_->HasLoadingClients()) { 608 scheduler_->HasLoadingClients()) {
595 update_load_states_timer_->Start( 609 update_load_states_timer_->Start(
596 FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), 610 FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec),
597 this, &ResourceDispatcherHostImpl::UpdateLoadInfo); 611 this, &ResourceDispatcherHostImpl::UpdateLoadInfo);
598 } 612 }
613 if (record_outstanding_requests_stats_timer_ &&
614 !record_outstanding_requests_stats_timer_->IsRunning()) {
615 record_outstanding_requests_stats_timer_->Start(
616 FROM_HERE,
617 TimeDelta::FromSeconds(kRecordOutstandingRequestsStatsIntervalSec),
618 this, &ResourceDispatcherHostImpl::RecordOutstandingRequestsStats);
619 }
599 } 620 }
600 621
601 void ResourceDispatcherHostImpl::DidReceiveRedirect( 622 void ResourceDispatcherHostImpl::DidReceiveRedirect(
602 ResourceLoader* loader, 623 ResourceLoader* loader,
603 const GURL& new_url, 624 const GURL& new_url,
604 ResourceResponse* response) { 625 ResourceResponse* response) {
605 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 626 ResourceRequestInfoImpl* info = loader->GetRequestInfo();
606 if (delegate_) { 627 if (delegate_) {
607 delegate_->OnRequestRedirected( 628 delegate_->OnRequestRedirected(
608 new_url, loader->request(), info->GetContext(), response); 629 new_url, loader->request(), info->GetContext(), response);
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 void ResourceDispatcherHostImpl::OnInit() { 798 void ResourceDispatcherHostImpl::OnInit() {
778 scheduler_.reset(new ResourceScheduler); 799 scheduler_.reset(new ResourceScheduler);
779 } 800 }
780 801
781 void ResourceDispatcherHostImpl::OnShutdown() { 802 void ResourceDispatcherHostImpl::OnShutdown() {
782 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); 803 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
783 804
784 is_shutdown_ = true; 805 is_shutdown_ = true;
785 pending_loaders_.clear(); 806 pending_loaders_.clear();
786 807
787 // Make sure we shutdown the timer now, otherwise by the time our destructor 808 // Make sure we shutdown the timers now, otherwise by the time our destructor
788 // runs if the timer is still running the Task is deleted twice (once by 809 // runs if the timer is still running the Task is deleted twice (once by
789 // the MessageLoop and the second time by RepeatingTimer). 810 // the MessageLoop and the second time by RepeatingTimer).
790 update_load_states_timer_.reset(); 811 update_load_states_timer_.reset();
812 record_outstanding_requests_stats_timer_.reset();
791 813
792 // Clear blocked requests if any left. 814 // Clear blocked requests if any left.
793 // Note that we have to do this in 2 passes as we cannot call 815 // Note that we have to do this in 2 passes as we cannot call
794 // CancelBlockedRequestsForRoute while iterating over 816 // CancelBlockedRequestsForRoute while iterating over
795 // blocked_loaders_map_, as it modifies it. 817 // blocked_loaders_map_, as it modifies it.
796 std::set<GlobalFrameRoutingId> ids; 818 std::set<GlobalFrameRoutingId> ids;
797 for (const auto& blocked_loaders : blocked_loaders_map_) { 819 for (const auto& blocked_loaders : blocked_loaders_map_) {
798 std::pair<std::set<GlobalFrameRoutingId>::iterator, bool> result = 820 std::pair<std::set<GlobalFrameRoutingId>::iterator, bool> result =
799 ids.insert(blocked_loaders.first); 821 ids.insert(blocked_loaders.first);
800 // We should not have duplicates. 822 // We should not have duplicates.
(...skipping 1111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1912 1934
1913 void ResourceDispatcherHostImpl::UpdateOutstandingRequestsStats( 1935 void ResourceDispatcherHostImpl::UpdateOutstandingRequestsStats(
1914 const ResourceRequestInfoImpl& info, 1936 const ResourceRequestInfoImpl& info,
1915 const OustandingRequestsStats& stats) { 1937 const OustandingRequestsStats& stats) {
1916 if (stats.memory_cost == 0 && stats.num_requests == 0) 1938 if (stats.memory_cost == 0 && stats.num_requests == 0)
1917 outstanding_requests_stats_map_.erase(info.GetChildID()); 1939 outstanding_requests_stats_map_.erase(info.GetChildID());
1918 else 1940 else
1919 outstanding_requests_stats_map_[info.GetChildID()] = stats; 1941 outstanding_requests_stats_map_[info.GetChildID()] = stats;
1920 } 1942 }
1921 1943
1944 void ResourceDispatcherHostImpl::IncrementOutstandingRequestsPerTab(
1945 int count,
1946 const ResourceRequestInfoImpl& info) {
1947 auto key = std::make_pair(info.GetChildID(), info.GetRouteID());
1948 OutstandingRequestsPerTabMap::iterator entry =
1949 outstanding_requests_per_tab_map_.insert(std::make_pair(key, 0)).first;
1950 entry->second += count;
1951 DCHECK_GE(entry->second, 0);
1952 if (entry->second == 0)
1953 outstanding_requests_per_tab_map_.erase(entry);
1954 }
1955
1922 ResourceDispatcherHostImpl::OustandingRequestsStats 1956 ResourceDispatcherHostImpl::OustandingRequestsStats
1923 ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemory( 1957 ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemory(
1924 int count, 1958 int count,
1925 const ResourceRequestInfoImpl& info) { 1959 const ResourceRequestInfoImpl& info) {
1926 DCHECK_EQ(1, abs(count)); 1960 DCHECK_EQ(1, abs(count));
1927 1961
1928 // Retrieve the previous value (defaulting to 0 if not found). 1962 // Retrieve the previous value (defaulting to 0 if not found).
1929 OustandingRequestsStats stats = GetOutstandingRequestsStats(info); 1963 OustandingRequestsStats stats = GetOutstandingRequestsStats(info);
1930 1964
1931 // Insert/update the total; delete entries when their count reaches 0. 1965 // Insert/update the total; delete entries when their count reaches 0.
(...skipping 15 matching lines...) Expand all
1947 // in-flight requests for this process, in case we need to transfer it to 1981 // in-flight requests for this process, in case we need to transfer it to
1948 // another process. This should be a toggle. 1982 // another process. This should be a toggle.
1949 DCHECK_NE(info->counted_as_in_flight_request(), count > 0); 1983 DCHECK_NE(info->counted_as_in_flight_request(), count > 0);
1950 info->set_counted_as_in_flight_request(count > 0); 1984 info->set_counted_as_in_flight_request(count > 0);
1951 1985
1952 OustandingRequestsStats stats = GetOutstandingRequestsStats(*info); 1986 OustandingRequestsStats stats = GetOutstandingRequestsStats(*info);
1953 stats.num_requests += count; 1987 stats.num_requests += count;
1954 DCHECK_GE(stats.num_requests, 0); 1988 DCHECK_GE(stats.num_requests, 0);
1955 UpdateOutstandingRequestsStats(*info, stats); 1989 UpdateOutstandingRequestsStats(*info, stats);
1956 1990
1991 IncrementOutstandingRequestsPerTab(count, *info);
1992
1957 if (num_in_flight_requests_ > largest_outstanding_request_count_seen_) { 1993 if (num_in_flight_requests_ > largest_outstanding_request_count_seen_) {
1958 largest_outstanding_request_count_seen_ = num_in_flight_requests_; 1994 largest_outstanding_request_count_seen_ = num_in_flight_requests_;
1959 UMA_HISTOGRAM_COUNTS_1M( 1995 UMA_HISTOGRAM_COUNTS_1M(
1960 "Net.ResourceDispatcherHost.OutstandingRequests.Total", 1996 "Net.ResourceDispatcherHost.OutstandingRequests.Total",
1961 largest_outstanding_request_count_seen_); 1997 largest_outstanding_request_count_seen_);
1962 } 1998 }
1963 1999
1964 if (stats.num_requests > 2000 if (stats.num_requests >
1965 largest_outstanding_request_per_process_count_seen_) { 2001 largest_outstanding_request_per_process_count_seen_) {
1966 largest_outstanding_request_per_process_count_seen_ = stats.num_requests; 2002 largest_outstanding_request_per_process_count_seen_ = stats.num_requests;
1967 UMA_HISTOGRAM_COUNTS_1M( 2003 UMA_HISTOGRAM_COUNTS_1M(
1968 "Net.ResourceDispatcherHost.OutstandingRequests.PerProcess", 2004 "Net.ResourceDispatcherHost.OutstandingRequests.PerProcess",
1969 largest_outstanding_request_per_process_count_seen_); 2005 largest_outstanding_request_per_process_count_seen_);
1970 } 2006 }
1971 2007
2008 if (num_in_flight_requests_ > peak_outstanding_request_count_)
2009 peak_outstanding_request_count_ = num_in_flight_requests_;
2010
2011 if (HasRequestsFromMultipleActiveTabs() &&
2012 num_in_flight_requests_ > peak_outstanding_request_count_multitab_) {
2013 peak_outstanding_request_count_multitab_ = num_in_flight_requests_;
2014 }
2015
1972 return stats; 2016 return stats;
1973 } 2017 }
1974 2018
1975 bool ResourceDispatcherHostImpl::HasSufficientResourcesForRequest( 2019 bool ResourceDispatcherHostImpl::HasSufficientResourcesForRequest(
1976 net::URLRequest* request) { 2020 net::URLRequest* request) {
1977 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); 2021 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
1978 OustandingRequestsStats stats = IncrementOutstandingRequestsCount(1, info); 2022 OustandingRequestsStats stats = IncrementOutstandingRequestsCount(1, info);
1979 2023
1980 if (stats.num_requests > max_num_in_flight_requests_per_process_) 2024 if (stats.num_requests > max_num_in_flight_requests_per_process_)
1981 return false; 2025 return false;
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
2490 // We need to be able to compare all requests to find the most important one 2534 // We need to be able to compare all requests to find the most important one
2491 // per tab. Since some requests may be navigation requests and we don't have 2535 // per tab. Since some requests may be navigation requests and we don't have
2492 // their render frame routing IDs yet (which is what we have for subresource 2536 // their render frame routing IDs yet (which is what we have for subresource
2493 // requests), we must go to the UI thread and compare the requests using their 2537 // requests), we must go to the UI thread and compare the requests using their
2494 // WebContents. 2538 // WebContents.
2495 main_thread_task_runner_->PostTask( 2539 main_thread_task_runner_->PostTask(
2496 FROM_HERE, 2540 FROM_HERE,
2497 base::Bind(UpdateLoadStateOnUI, loader_delegate_, base::Passed(&infos))); 2541 base::Bind(UpdateLoadStateOnUI, loader_delegate_, base::Passed(&infos)));
2498 } 2542 }
2499 2543
2544 void ResourceDispatcherHostImpl::RecordOutstandingRequestsStats() {
2545 if (peak_outstanding_request_count_ != 0) {
2546 UMA_HISTOGRAM_COUNTS_1M(
2547 "Net.ResourceDispatcherHost.PeakOutstandingRequests",
2548 peak_outstanding_request_count_);
2549 peak_outstanding_request_count_ = num_in_flight_requests_;
2550 }
2551
2552 if (peak_outstanding_request_count_multitab_ != 0) {
2553 UMA_HISTOGRAM_COUNTS_1M(
2554 "Net.ResourceDispatcherHost.PeakOutstandingRequests.MultiTabLoading",
2555 peak_outstanding_request_count_multitab_);
2556 peak_outstanding_request_count_multitab_ =
2557 HasRequestsFromMultipleActiveTabs() ? num_in_flight_requests_ : 0;
2558 }
2559 }
2560
2500 void ResourceDispatcherHostImpl::BlockRequestsForRoute( 2561 void ResourceDispatcherHostImpl::BlockRequestsForRoute(
2501 const GlobalFrameRoutingId& global_routing_id) { 2562 const GlobalFrameRoutingId& global_routing_id) {
2502 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); 2563 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
2503 DCHECK(blocked_loaders_map_.find(global_routing_id) == 2564 DCHECK(blocked_loaders_map_.find(global_routing_id) ==
2504 blocked_loaders_map_.end()) 2565 blocked_loaders_map_.end())
2505 << "BlockRequestsForRoute called multiple time for the same RFH"; 2566 << "BlockRequestsForRoute called multiple time for the same RFH";
2506 blocked_loaders_map_[global_routing_id] = 2567 blocked_loaders_map_[global_routing_id] =
2507 base::MakeUnique<BlockedLoadersList>(); 2568 base::MakeUnique<BlockedLoadersList>();
2508 } 2569 }
2509 2570
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
2699 is_content_initiated, true, is_new_request, 2760 is_content_initiated, true, is_new_request,
2700 &throttles); 2761 &throttles);
2701 if (!throttles.empty()) { 2762 if (!throttles.empty()) {
2702 handler.reset(new ThrottlingResourceHandler(std::move(handler), request, 2763 handler.reset(new ThrottlingResourceHandler(std::move(handler), request,
2703 std::move(throttles))); 2764 std::move(throttles)));
2704 } 2765 }
2705 } 2766 }
2706 return handler; 2767 return handler;
2707 } 2768 }
2708 2769
2770 bool ResourceDispatcherHostImpl::HasRequestsFromMultipleActiveTabs() {
2771 if (outstanding_requests_per_tab_map_.size() < 2)
2772 return false;
2773
2774 int active_tabs = 0;
2775 for (auto iter = outstanding_requests_per_tab_map_.begin();
2776 iter != outstanding_requests_per_tab_map_.end(); ++iter) {
2777 if (iter->second > 2) {
2778 active_tabs++;
2779 if (active_tabs >= 2)
2780 return true;
2781 }
2782 }
2783 return false;
2784 }
2785
2709 } // namespace content 2786 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/resource_dispatcher_host_impl.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698