Chromium Code Reviews| Index: chrome/browser/resource_coordinator/tab_manager.cc |
| diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc |
| index 9db21d6569932f5287a3937a778a60f2b2db8b68..0337b40d62954d1cf7dd049675c73a3620d8594a 100644 |
| --- a/chrome/browser/resource_coordinator/tab_manager.cc |
| +++ b/chrome/browser/resource_coordinator/tab_manager.cc |
| @@ -11,7 +11,6 @@ |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| -#include "base/command_line.h" |
| #include "base/feature_list.h" |
| #include "base/memory/memory_pressure_monitor.h" |
| #include "base/metrics/field_trial.h" |
| @@ -42,12 +41,12 @@ |
| #include "chrome/browser/ui/tabs/tab_utils.h" |
| #include "chrome/common/chrome_constants.h" |
| #include "chrome/common/chrome_features.h" |
| -#include "chrome/common/chrome_switches.h" |
| #include "chrome/common/url_constants.h" |
| #include "components/metrics/system_memory_stats_recorder.h" |
| #include "components/variations/variations_associated_data.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/navigation_controller.h" |
| +#include "content/public/browser/navigation_handle.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/content_features.h" |
| @@ -841,6 +840,8 @@ void TabManager::ActiveTabChanged(content::WebContents* old_contents, |
| ReloadWebContentsIfDiscarded(new_contents, |
| GetWebContentsData(new_contents)); |
| } |
| + |
| + ResumeTabNavigationIfNeeded(new_contents); |
| } |
| void TabManager::TabInsertedAt(TabStripModel* tab_strip_model, |
| @@ -976,4 +977,124 @@ void TabManager::RecordSwitchToTab(content::WebContents* contents) const { |
| } |
| } |
| +content::NavigationThrottle::ThrottleCheckResult |
| +TabManager::MaybeThrottleNavigation( |
| + content::NavigationHandle* navigation_handle) { |
| + if (!ShouldDelayNavigation(navigation_handle)) { |
| + loading_contents_.insert(navigation_handle->GetWebContents()); |
| + return content::NavigationThrottle::PROCEED; |
| + } |
| + |
| + // TODO(zhenw): Try to set the favicon and title from history service if this |
| + // navigation will be delayed. |
| + GetWebContentsData(navigation_handle->GetWebContents()) |
| + ->SetTabLoadingState(TAB_IS_NOT_LOADING); |
| + pending_navigations_.push_back(navigation_handle); |
| + |
| + return content::NavigationThrottle::DEFER; |
| +} |
| + |
| +bool TabManager::ShouldDelayNavigation( |
| + content::NavigationHandle* navigation_handle) const { |
| + if (!navigation_handle) |
| + return false; |
| + |
| + // Do not delay the navigation if no tab is currently loading. |
| + if (loading_contents_.empty()) { |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +void TabManager::OnNavigationDone( |
| + content::NavigationHandle* navigation_handle) { |
| + auto it = pending_navigations_.begin(); |
| + while (it != pending_navigations_.end()) { |
| + content::NavigationHandle* pending_handle = *it; |
| + if (pending_handle == navigation_handle) { |
| + pending_navigations_.erase(it); |
| + break; |
| + } |
| + it++; |
| + } |
| +} |
| + |
| +void TabManager::OnLoadingDone(content::WebContents* contents) { |
| + DCHECK(GetWebContentsData(contents)->tab_loading_state() == TAB_IS_LOADED); |
|
Charlie Reis
2017/07/06 23:50:30
nit: Does DCHECK_EQ work here? That would give a
Zhen Wang
2017/07/07 18:06:39
Done.
|
| + loading_contents_.erase(contents); |
| + LoadNextBackgroundTabIfNeeded(); |
| +} |
| + |
| +void TabManager::OnWebContentsDestroyed(content::WebContents* contents) { |
| + RemovePendingNavigationIfNeeded(contents); |
| + loading_contents_.erase(contents); |
| + LoadNextBackgroundTabIfNeeded(); |
| +} |
| + |
| +void TabManager::LoadNextBackgroundTabIfNeeded() { |
| + // Do not load more background tabs until all currently loading tabs have |
| + // finished. |
| + if (!loading_contents_.empty()) |
| + return; |
| + |
| + if (pending_navigations_.empty()) |
| + return; |
| + |
| + content::NavigationHandle* navigation_handle = pending_navigations_.front(); |
| + pending_navigations_.erase(pending_navigations_.begin()); |
| + ResumeNavigation(navigation_handle); |
| +} |
| + |
| +void TabManager::ResumeTabNavigationIfNeeded(content::WebContents* contents) { |
| + content::NavigationHandle* navigation_handle = |
| + RemovePendingNavigationIfNeeded(contents); |
| + if (navigation_handle) |
| + ResumeNavigation(navigation_handle); |
| +} |
| + |
| +void TabManager::ResumeNavigation( |
| + content::NavigationHandle* navigation_handle) { |
| + GetWebContentsData(navigation_handle->GetWebContents()) |
| + ->SetTabLoadingState(TAB_IS_LOADING); |
| + loading_contents_.insert(navigation_handle->GetWebContents()); |
| + |
| + navigation_handle->Resume(); |
| +} |
| + |
| +content::NavigationHandle* TabManager::RemovePendingNavigationIfNeeded( |
| + content::WebContents* contents) { |
| + content::NavigationHandle* navigation_handle = nullptr; |
| + auto it = pending_navigations_.begin(); |
| + while (it != pending_navigations_.end()) { |
| + navigation_handle = *it; |
| + if ((*it)->GetWebContents() == contents) { |
| + navigation_handle = *it; |
| + pending_navigations_.erase(it); |
| + break; |
| + } |
| + it++; |
| + } |
| + return navigation_handle; |
| +} |
| + |
| +bool TabManager::IsTabLoadingForTest(content::WebContents* contents) const { |
| + if (loading_contents_.count(contents) == 1) { |
| + DCHECK(GetWebContentsData(contents)->tab_loading_state() == TAB_IS_LOADING); |
| + return true; |
| + } |
| + |
| + DCHECK(GetWebContentsData(contents)->tab_loading_state() != TAB_IS_LOADING); |
| + return false; |
| +} |
| + |
| +bool TabManager::IsNavigationDelayedForTest( |
| + const content::NavigationHandle* navigation_handle) const { |
| + for (const auto* nav : pending_navigations_) { |
| + if (nav == navigation_handle) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| } // namespace resource_coordinator |