| OLD | NEW |
| 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 #include "chrome/browser/memory/tab_manager.h" | 5 #include "chrome/browser/memory/tab_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> |
| 8 |
| 7 #include <algorithm> | 9 #include <algorithm> |
| 8 #include <set> | 10 #include <set> |
| 9 #include <vector> | 11 #include <vector> |
| 10 | 12 |
| 11 #include "ash/multi_profile_uma.h" | 13 #include "ash/multi_profile_uma.h" |
| 12 #include "ash/session/session_state_delegate.h" | 14 #include "ash/session/session_state_delegate.h" |
| 13 #include "ash/shell.h" | 15 #include "ash/shell.h" |
| 14 #include "base/bind.h" | 16 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 17 #include "base/bind_helpers.h" |
| 16 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 19 #include "base/macros.h" |
| 17 #include "base/memory/memory_pressure_monitor.h" | 20 #include "base/memory/memory_pressure_monitor.h" |
| 18 #include "base/metrics/field_trial.h" | 21 #include "base/metrics/field_trial.h" |
| 19 #include "base/metrics/histogram.h" | 22 #include "base/metrics/histogram.h" |
| 20 #include "base/process/process.h" | 23 #include "base/process/process.h" |
| 21 #include "base/strings/string16.h" | 24 #include "base/strings/string16.h" |
| 22 #include "base/strings/string_number_conversions.h" | 25 #include "base/strings/string_number_conversions.h" |
| 23 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
| 24 #include "base/strings/utf_string_conversions.h" | 27 #include "base/strings/utf_string_conversions.h" |
| 25 #include "base/threading/thread.h" | 28 #include "base/threading/thread.h" |
| 26 #include "build/build_config.h" | 29 #include "build/build_config.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 // If there has been no priority adjustment in this interval, assume the | 71 // If there has been no priority adjustment in this interval, assume the |
| 69 // machine was suspended and correct the timing statistics. | 72 // machine was suspended and correct the timing statistics. |
| 70 const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4; | 73 const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4; |
| 71 | 74 |
| 72 // The time during which a tab is protected from discarding after it stops being | 75 // The time during which a tab is protected from discarding after it stops being |
| 73 // audible. | 76 // audible. |
| 74 const int kAudioProtectionTimeSeconds = 60; | 77 const int kAudioProtectionTimeSeconds = 60; |
| 75 | 78 |
| 76 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as | 79 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as |
| 77 // the WebContents could be deleted if the user closed the tab. | 80 // the WebContents could be deleted if the user closed the tab. |
| 78 int64 IdFromWebContents(WebContents* web_contents) { | 81 int64_t IdFromWebContents(WebContents* web_contents) { |
| 79 return reinterpret_cast<int64>(web_contents); | 82 return reinterpret_cast<int64_t>(web_contents); |
| 80 } | 83 } |
| 81 | 84 |
| 82 int FindTabStripModelById(int64 target_web_contents_id, TabStripModel** model) { | 85 int FindTabStripModelById(int64_t target_web_contents_id, |
| 86 TabStripModel** model) { |
| 83 DCHECK(model); | 87 DCHECK(model); |
| 84 for (chrome::BrowserIterator it; !it.done(); it.Next()) { | 88 for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
| 85 Browser* browser = *it; | 89 Browser* browser = *it; |
| 86 TabStripModel* local_model = browser->tab_strip_model(); | 90 TabStripModel* local_model = browser->tab_strip_model(); |
| 87 for (int idx = 0; idx < local_model->count(); idx++) { | 91 for (int idx = 0; idx < local_model->count(); idx++) { |
| 88 WebContents* web_contents = local_model->GetWebContentsAt(idx); | 92 WebContents* web_contents = local_model->GetWebContentsAt(idx); |
| 89 int64 web_contents_id = IdFromWebContents(web_contents); | 93 int64_t web_contents_id = IdFromWebContents(web_contents); |
| 90 if (web_contents_id == target_web_contents_id) { | 94 if (web_contents_id == target_web_contents_id) { |
| 91 *model = local_model; | 95 *model = local_model; |
| 92 return idx; | 96 return idx; |
| 93 } | 97 } |
| 94 } | 98 } |
| 95 } | 99 } |
| 96 | 100 |
| 97 return -1; | 101 return -1; |
| 98 } | 102 } |
| 99 | 103 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 // such as tabs created with JavaScript window.open(). Potentially consider | 192 // such as tabs created with JavaScript window.open(). Potentially consider |
| 189 // discarding the entire set together, or use that in the priority computation. | 193 // discarding the entire set together, or use that in the priority computation. |
| 190 bool TabManager::DiscardTab() { | 194 bool TabManager::DiscardTab() { |
| 191 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 195 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 192 TabStatsList stats = GetTabStats(); | 196 TabStatsList stats = GetTabStats(); |
| 193 if (stats.empty()) | 197 if (stats.empty()) |
| 194 return false; | 198 return false; |
| 195 // Loop until a non-discarded tab to kill is found. | 199 // Loop until a non-discarded tab to kill is found. |
| 196 for (TabStatsList::const_reverse_iterator stats_rit = stats.rbegin(); | 200 for (TabStatsList::const_reverse_iterator stats_rit = stats.rbegin(); |
| 197 stats_rit != stats.rend(); ++stats_rit) { | 201 stats_rit != stats.rend(); ++stats_rit) { |
| 198 int64 least_important_tab_id = stats_rit->tab_contents_id; | 202 int64_t least_important_tab_id = stats_rit->tab_contents_id; |
| 199 if (CanDiscardTab(least_important_tab_id) && | 203 if (CanDiscardTab(least_important_tab_id) && |
| 200 DiscardTabById(least_important_tab_id)) | 204 DiscardTabById(least_important_tab_id)) |
| 201 return true; | 205 return true; |
| 202 } | 206 } |
| 203 return false; | 207 return false; |
| 204 } | 208 } |
| 205 | 209 |
| 206 WebContents* TabManager::DiscardTabById(int64 target_web_contents_id) { | 210 WebContents* TabManager::DiscardTabById(int64_t target_web_contents_id) { |
| 207 TabStripModel* model; | 211 TabStripModel* model; |
| 208 int index = FindTabStripModelById(target_web_contents_id, &model); | 212 int index = FindTabStripModelById(target_web_contents_id, &model); |
| 209 | 213 |
| 210 if (index == -1) | 214 if (index == -1) |
| 211 return nullptr; | 215 return nullptr; |
| 212 | 216 |
| 213 VLOG(1) << "Discarding tab " << index << " id " << target_web_contents_id; | 217 VLOG(1) << "Discarding tab " << index << " id " << target_web_contents_id; |
| 214 | 218 |
| 215 return DiscardWebContentsAt(index, model); | 219 return DiscardWebContentsAt(index, model); |
| 216 } | 220 } |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 } | 432 } |
| 429 last_adjust_time_ = TimeTicks::Now(); | 433 last_adjust_time_ = TimeTicks::Now(); |
| 430 | 434 |
| 431 #if defined(OS_CHROMEOS) | 435 #if defined(OS_CHROMEOS) |
| 432 TabStatsList stats_list = GetTabStats(); | 436 TabStatsList stats_list = GetTabStats(); |
| 433 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. | 437 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. |
| 434 delegate_->AdjustOomPriorities(stats_list); | 438 delegate_->AdjustOomPriorities(stats_list); |
| 435 #endif | 439 #endif |
| 436 } | 440 } |
| 437 | 441 |
| 438 bool TabManager::CanDiscardTab(int64 target_web_contents_id) const { | 442 bool TabManager::CanDiscardTab(int64_t target_web_contents_id) const { |
| 439 TabStripModel* model; | 443 TabStripModel* model; |
| 440 int idx = FindTabStripModelById(target_web_contents_id, &model); | 444 int idx = FindTabStripModelById(target_web_contents_id, &model); |
| 441 | 445 |
| 442 if (idx == -1) | 446 if (idx == -1) |
| 443 return false; | 447 return false; |
| 444 | 448 |
| 445 WebContents* web_contents = model->GetWebContentsAt(idx); | 449 WebContents* web_contents = model->GetWebContentsAt(idx); |
| 446 | 450 |
| 447 // Do not discard tabs that don't have a valid URL (most probably they have | 451 // Do not discard tabs that don't have a valid URL (most probably they have |
| 448 // just been opened and dicarding them would lose the URL). | 452 // just been opened and dicarding them would lose the URL). |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 // sudden_termination_allowed false, and that covers too many common pages | 591 // sudden_termination_allowed false, and that covers too many common pages |
| 588 // with ad networks and statistics scripts. Ideally check for beforeUnload | 592 // with ad networks and statistics scripts. Ideally check for beforeUnload |
| 589 // handlers, which are likely to present a dialog asking if the user wants to | 593 // handlers, which are likely to present a dialog asking if the user wants to |
| 590 // discard state. crbug.com/123049. | 594 // discard state. crbug.com/123049. |
| 591 | 595 |
| 592 // Being more recently active is more important. | 596 // Being more recently active is more important. |
| 593 return first.last_active > second.last_active; | 597 return first.last_active > second.last_active; |
| 594 } | 598 } |
| 595 | 599 |
| 596 } // namespace memory | 600 } // namespace memory |
| OLD | NEW |