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

Unified Diff: chrome/browser/memory/tab_manager.cc

Issue 2228473003: Order TabManager functions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/memory/tab_manager.cc
diff --git a/chrome/browser/memory/tab_manager.cc b/chrome/browser/memory/tab_manager.cc
index 296947636c5982a7aeaf5ebff72212798dda0123..a99e6abdc048bd79f91e73bd4fe68c6b523fc5f1 100644
--- a/chrome/browser/memory/tab_manager.cc
+++ b/chrome/browser/memory/tab_manager.cc
@@ -271,6 +271,62 @@ bool TabManager::IsTabDiscarded(content::WebContents* contents) const {
return GetWebContentsData(contents)->IsDiscarded();
}
+bool TabManager::CanDiscardTab(int64_t target_web_contents_id) const {
+ TabStripModel* model;
+ int idx = FindTabStripModelById(target_web_contents_id, &model);
+
+ if (idx == -1)
+ return false;
+
+ WebContents* web_contents = model->GetWebContentsAt(idx);
+
+ // Do not discard tabs that don't have a valid URL (most probably they have
+ // just been opened and dicarding them would lose the URL).
+ // TODO(georgesak): Look into a workaround to be able to kill the tab without
+ // losing the pending navigation.
+ if (!web_contents->GetLastCommittedURL().is_valid() ||
+ web_contents->GetLastCommittedURL().is_empty()) {
+ return false;
+ }
+
+ // Do not discard tabs in which the user has entered text in a form, lest that
+ // state gets lost.
+ if (web_contents->GetPageImportanceSignals().had_form_interaction)
+ return false;
+
+ // Do not discard tabs that are playing either playing audio or accessing the
+ // microphone or camera as it's too distruptive to the user experience. Note
+ // that tabs that have recently stopped playing audio by at least
+ // |kAudioProtectionTimeSeconds| seconds are protected as well.
+ if (IsMediaTab(web_contents))
+ return false;
+
+ // Do not discard PDFs as they might contain entry that is not saved and they
+ // don't remember their scrolling positions. See crbug.com/547286 and
+ // crbug.com/65244.
+ // TODO(georgesak): Remove this workaround when the bugs are fixed.
+ if (web_contents->GetContentsMimeType() == "application/pdf")
+ return false;
+
+ // Do not discard a previously discarded tab if that's the desired behavior.
+ if (discard_once_ && GetWebContentsData(web_contents)->DiscardCount() > 0)
+ return false;
+
+ // Do not discard a recently used tab.
+ if (minimum_protection_time_.InSeconds() > 0) {
+ auto delta =
+ NowTicks() - GetWebContentsData(web_contents)->LastInactiveTime();
+ if (delta < minimum_protection_time_)
+ return false;
+ }
+
+ // Do not discard a tab that was explicitly disallowed to.
+ if (!IsTabAutoDiscardable(web_contents))
+ return false;
+
+ return true;
+}
+
void TabManager::DiscardTab() {
#if defined(OS_CHROMEOS)
// Call Chrome OS specific low memory handling process.
@@ -316,47 +372,115 @@ void TabManager::set_test_tick_clock(base::TickClock* test_tick_clock) {
test_tick_clock_ = test_tick_clock;
}
-void TabManager::TabChangedAt(content::WebContents* contents,
- int index,
- TabChangeType change_type) {
- if (change_type != TabChangeType::ALL)
- return;
- auto* data = GetWebContentsData(contents);
- bool old_state = data->IsRecentlyAudible();
- bool current_state = contents->WasRecentlyAudible();
- if (old_state != current_state) {
- data->SetRecentlyAudible(current_state);
- data->SetLastAudioChangeTime(NowTicks());
+// Things to collect on the browser thread (because TabStripModel isn't thread
+// safe):
+// 1) whether or not a tab is pinned
+// 2) last time a tab was selected
+// 3) is the tab currently selected
+TabStatsList TabManager::GetUnsortedTabStats() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ TabStatsList stats_list;
+ stats_list.reserve(32); // 99% of users have < 30 tabs open.
+
+ // TODO(chrisha): Move this code to a TabStripModel enumeration delegate!
+ if (!test_tab_strip_models_.empty()) {
+ for (size_t i = 0; i < test_tab_strip_models_.size(); ++i) {
+ AddTabStats(test_tab_strip_models_[i].first, // tab_strip_model
+ test_tab_strip_models_[i].second, // is_app
+ i == 0, // is_active
+ &stats_list);
+ }
+ } else {
+ // The code here can only be tested under a full browser test.
+ AddTabStats(&stats_list);
}
+
+ return stats_list;
}
-void TabManager::ActiveTabChanged(content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index,
- int reason) {
- GetWebContentsData(new_contents)->SetDiscardState(false);
- // If |old_contents| is set, that tab has switched from being active to
- // inactive, so record the time of that transition.
- if (old_contents)
- GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks());
+void TabManager::AddObserver(TabManagerObserver* observer) {
+ observers_.AddObserver(observer);
}
-void TabManager::TabInsertedAt(content::WebContents* contents,
- int index,
- bool foreground) {
- // Only interested in background tabs, as foreground tabs get taken care of by
- // ActiveTabChanged.
- if (foreground)
- return;
+void TabManager::RemoveObserver(TabManagerObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
- // A new background tab is similar to having a tab switch from being active to
- // inactive.
- GetWebContentsData(contents)->SetLastInactiveTime(NowTicks());
+void TabManager::set_minimum_protection_time_for_tests(
+ base::TimeDelta minimum_protection_time) {
+ minimum_protection_time_ = minimum_protection_time;
+}
+
+bool TabManager::IsTabAutoDiscardable(content::WebContents* contents) const {
+ return GetWebContentsData(contents)->IsAutoDiscardable();
+}
+
+void TabManager::SetTabAutoDiscardableState(content::WebContents* contents,
+ bool state) {
+ GetWebContentsData(contents)->SetAutoDiscardableState(state);
+}
+
+// static
+bool TabManager::CompareTabStats(const TabStats& first,
+ const TabStats& second) {
+ // Being currently selected is most important to protect.
+ if (first.is_selected != second.is_selected)
+ return first.is_selected;
+
+ // Non auto-discardable tabs are more important to protect.
+ if (first.is_auto_discardable != second.is_auto_discardable)
+ return !first.is_auto_discardable;
+
+ // Protect tabs with pending form entries.
+ if (first.has_form_entry != second.has_form_entry)
+ return first.has_form_entry;
+
+ // Protect streaming audio and video conferencing tabs as these are similar to
+ // active tabs.
+ if (first.is_media != second.is_media)
+ return first.is_media;
+
+ // Tab with internal web UI like NTP or Settings are good choices to discard,
+ // so protect non-Web UI and let the other conditionals finish the sort.
+ if (first.is_internal_page != second.is_internal_page)
+ return !first.is_internal_page;
+
+ // Being pinned is important to protect.
+ if (first.is_pinned != second.is_pinned)
+ return first.is_pinned;
+
+ // Being an app is important too, as it's the only visible surface in the
+ // window and should not be discarded.
+ if (first.is_app != second.is_app)
+ return first.is_app;
+
+ // TODO(jamescook): Incorporate sudden_termination_allowed into the sort
+ // order. This is currently not done because pages with unload handlers set
+ // sudden_termination_allowed false, and that covers too many common pages
+ // with ad networks and statistics scripts. Ideally check for beforeUnload
+ // handlers, which are likely to present a dialog asking if the user wants to
+ // discard state. crbug.com/123049.
+
+ // Being more recently active is more important.
+ return first.last_active > second.last_active;
}
///////////////////////////////////////////////////////////////////////////////
// TabManager, private:
+void TabManager::OnDiscardedStateChange(content::WebContents* contents,
+ bool is_discarded) {
+ FOR_EACH_OBSERVER(TabManagerObserver, observers_,
+ OnDiscardedStateChange(contents, is_discarded));
+}
+
+void TabManager::OnAutoDiscardableStateChange(content::WebContents* contents,
+ bool is_auto_discardable) {
+ FOR_EACH_OBSERVER(
+ TabManagerObserver, observers_,
+ OnAutoDiscardableStateChange(contents, is_auto_discardable));
+}
+
// static
void TabManager::PurgeMemoryAndDiscardTab() {
if (g_browser_process && g_browser_process->GetTabManager()) {
@@ -488,8 +612,7 @@ void TabManager::AddTabStats(const TabStripModel* model,
if (!contents->IsCrashed()) {
TabStats stats;
stats.is_app = is_app;
- stats.is_internal_page =
- IsInternalPage(contents->GetLastCommittedURL());
+ stats.is_internal_page = IsInternalPage(contents->GetLastCommittedURL());
stats.is_media = IsMediaTab(contents);
stats.is_pinned = model->IsTabPinned(i);
stats.is_selected = active_model && model->IsTabSelected(i);
@@ -575,62 +698,6 @@ void TabManager::PurgeAndSuspendBackgroundedTabs() {
}
}
-bool TabManager::CanDiscardTab(int64_t target_web_contents_id) const {
- TabStripModel* model;
- int idx = FindTabStripModelById(target_web_contents_id, &model);
-
- if (idx == -1)
- return false;
-
- WebContents* web_contents = model->GetWebContentsAt(idx);
-
- // Do not discard tabs that don't have a valid URL (most probably they have
- // just been opened and dicarding them would lose the URL).
- // TODO(georgesak): Look into a workaround to be able to kill the tab without
- // losing the pending navigation.
- if (!web_contents->GetLastCommittedURL().is_valid() ||
- web_contents->GetLastCommittedURL().is_empty()) {
- return false;
- }
-
- // Do not discard tabs in which the user has entered text in a form, lest that
- // state gets lost.
- if (web_contents->GetPageImportanceSignals().had_form_interaction)
- return false;
-
- // Do not discard tabs that are playing either playing audio or accessing the
- // microphone or camera as it's too distruptive to the user experience. Note
- // that tabs that have recently stopped playing audio by at least
- // |kAudioProtectionTimeSeconds| seconds are protected as well.
- if (IsMediaTab(web_contents))
- return false;
-
- // Do not discard PDFs as they might contain entry that is not saved and they
- // don't remember their scrolling positions. See crbug.com/547286 and
- // crbug.com/65244.
- // TODO(georgesak): Remove this workaround when the bugs are fixed.
- if (web_contents->GetContentsMimeType() == "application/pdf")
- return false;
-
- // Do not discard a previously discarded tab if that's the desired behavior.
- if (discard_once_ && GetWebContentsData(web_contents)->DiscardCount() > 0)
- return false;
-
- // Do not discard a recently used tab.
- if (minimum_protection_time_.InSeconds() > 0) {
- auto delta =
- NowTicks() - GetWebContentsData(web_contents)->LastInactiveTime();
- if (delta < minimum_protection_time_)
- return false;
- }
-
- // Do not discard a tab that was explicitly disallowed to.
- if (!IsTabAutoDiscardable(web_contents))
- return false;
-
- return true;
-}
-
WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) {
// Can't discard active index.
if (model->active_index() == index)
@@ -709,6 +776,44 @@ void TabManager::OnMemoryPressure(
#endif
}
+void TabManager::TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) {
+ if (change_type != TabChangeType::ALL)
+ return;
+ auto* data = GetWebContentsData(contents);
+ bool old_state = data->IsRecentlyAudible();
+ bool current_state = contents->WasRecentlyAudible();
+ if (old_state != current_state) {
+ data->SetRecentlyAudible(current_state);
+ data->SetLastAudioChangeTime(NowTicks());
+ }
+}
+
+void TabManager::ActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) {
+ GetWebContentsData(new_contents)->SetDiscardState(false);
+ // If |old_contents| is set, that tab has switched from being active to
+ // inactive, so record the time of that transition.
+ if (old_contents)
+ GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks());
+}
+
+void TabManager::TabInsertedAt(content::WebContents* contents,
+ int index,
+ bool foreground) {
+ // Only interested in background tabs, as foreground tabs get taken care of by
+ // ActiveTabChanged.
+ if (foreground)
+ return;
+
+ // A new background tab is similar to having a tab switch from being active to
+ // inactive.
+ GetWebContentsData(contents)->SetLastInactiveTime(NowTicks());
+}
+
bool TabManager::IsMediaTab(WebContents* contents) const {
if (contents->WasRecentlyAudible())
return true;
@@ -733,51 +838,6 @@ TabManager::WebContentsData* TabManager::GetWebContentsData(
return web_contents_data;
}
-// static
-bool TabManager::CompareTabStats(const TabStats& first,
- const TabStats& second) {
- // Being currently selected is most important to protect.
- if (first.is_selected != second.is_selected)
- return first.is_selected;
-
- // Non auto-discardable tabs are more important to protect.
- if (first.is_auto_discardable != second.is_auto_discardable)
- return !first.is_auto_discardable;
-
- // Protect tabs with pending form entries.
- if (first.has_form_entry != second.has_form_entry)
- return first.has_form_entry;
-
- // Protect streaming audio and video conferencing tabs as these are similar to
- // active tabs.
- if (first.is_media != second.is_media)
- return first.is_media;
-
- // Tab with internal web UI like NTP or Settings are good choices to discard,
- // so protect non-Web UI and let the other conditionals finish the sort.
- if (first.is_internal_page != second.is_internal_page)
- return !first.is_internal_page;
-
- // Being pinned is important to protect.
- if (first.is_pinned != second.is_pinned)
- return first.is_pinned;
-
- // Being an app is important too, as it's the only visible surface in the
- // window and should not be discarded.
- if (first.is_app != second.is_app)
- return first.is_app;
-
- // TODO(jamescook): Incorporate sudden_termination_allowed into the sort
- // order. This is currently not done because pages with unload handlers set
- // sudden_termination_allowed false, and that covers too many common pages
- // with ad networks and statistics scripts. Ideally check for beforeUnload
- // handlers, which are likely to present a dialog asking if the user wants to
- // discard state. crbug.com/123049.
-
- // Being more recently active is more important.
- return first.last_active > second.last_active;
-}
-
TimeTicks TabManager::NowTicks() const {
if (!test_tick_clock_)
return TimeTicks::Now();
@@ -884,65 +944,4 @@ bool TabManager::CanOnlyDiscardOnce() {
#endif
}
-// Things to collect on the browser thread (because TabStripModel isn't thread
-// safe):
-// 1) whether or not a tab is pinned
-// 2) last time a tab was selected
-// 3) is the tab currently selected
-TabStatsList TabManager::GetUnsortedTabStats() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- TabStatsList stats_list;
- stats_list.reserve(32); // 99% of users have < 30 tabs open.
-
- // TODO(chrisha): Move this code to a TabStripModel enumeration delegate!
- if (!test_tab_strip_models_.empty()) {
- for (size_t i = 0; i < test_tab_strip_models_.size(); ++i) {
- AddTabStats(test_tab_strip_models_[i].first, // tab_strip_model
- test_tab_strip_models_[i].second, // is_app
- i == 0, // is_active
- &stats_list);
- }
- } else {
- // The code here can only be tested under a full browser test.
- AddTabStats(&stats_list);
- }
-
- return stats_list;
-}
-
-void TabManager::AddObserver(TabManagerObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void TabManager::RemoveObserver(TabManagerObserver* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void TabManager::OnDiscardedStateChange(content::WebContents* contents,
- bool is_discarded) {
- FOR_EACH_OBSERVER(TabManagerObserver, observers_,
- OnDiscardedStateChange(contents, is_discarded));
-}
-
-void TabManager::set_minimum_protection_time_for_tests(
- base::TimeDelta minimum_protection_time) {
- minimum_protection_time_ = minimum_protection_time;
-}
-
-void TabManager::OnAutoDiscardableStateChange(content::WebContents* contents,
- bool is_auto_discardable) {
- FOR_EACH_OBSERVER(
- TabManagerObserver, observers_,
- OnAutoDiscardableStateChange(contents, is_auto_discardable));
-}
-
-bool TabManager::IsTabAutoDiscardable(content::WebContents* contents) const {
- return GetWebContentsData(contents)->IsAutoDiscardable();
-}
-
-void TabManager::SetTabAutoDiscardableState(content::WebContents* contents,
- bool state) {
- GetWebContentsData(contents)->SetAutoDiscardableState(state);
-}
-
} // namespace memory
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698