OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/browser/frame_host/navigation_entry_screenshot_manager.h" | 5 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/threading/worker_pool.h" | 8 #include "base/threading/worker_pool.h" |
9 #include "content/browser/frame_host/navigation_controller_impl.h" | 9 #include "content/browser/frame_host/navigation_controller_impl.h" |
10 #include "content/browser/frame_host/navigation_entry_impl.h" | 10 #include "content/browser/frame_host/navigation_entry_impl.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 | 71 |
72 NavigationEntryScreenshotManager::~NavigationEntryScreenshotManager() { | 72 NavigationEntryScreenshotManager::~NavigationEntryScreenshotManager() { |
73 } | 73 } |
74 | 74 |
75 void NavigationEntryScreenshotManager::TakeScreenshot() { | 75 void NavigationEntryScreenshotManager::TakeScreenshot() { |
76 static bool overscroll_enabled = base::CommandLine::ForCurrentProcess()-> | 76 static bool overscroll_enabled = base::CommandLine::ForCurrentProcess()-> |
77 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0"; | 77 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0"; |
78 if (!overscroll_enabled) | 78 if (!overscroll_enabled) |
79 return; | 79 return; |
80 | 80 |
81 NavigationEntryImpl* entry = | 81 NavigationEntryImpl* entry = owner_->GetLastCommittedEntry(); |
82 NavigationEntryImpl::FromNavigationEntry(owner_->GetLastCommittedEntry()); | |
83 if (!entry) | 82 if (!entry) |
84 return; | 83 return; |
85 | 84 |
86 if (!owner_->delegate()->CanOverscrollContent()) | 85 if (!owner_->delegate()->CanOverscrollContent()) |
87 return; | 86 return; |
88 | 87 |
89 RenderViewHost* render_view_host = | 88 RenderViewHost* render_view_host = |
90 owner_->delegate()->GetRenderViewHost(); | 89 owner_->delegate()->GetRenderViewHost(); |
91 content::RenderWidgetHostView* view = render_view_host->GetView(); | 90 content::RenderWidgetHostView* view = render_view_host->GetView(); |
92 if (!view) | 91 if (!view) |
93 return; | 92 return; |
94 | 93 |
95 // Make sure screenshots aren't taken too frequently. | 94 // Make sure screenshots aren't taken too frequently. |
96 base::Time now = base::Time::Now(); | 95 base::Time now = base::Time::Now(); |
97 if (now - last_screenshot_time_ < | 96 if (now - last_screenshot_time_ < |
98 base::TimeDelta::FromMilliseconds(min_screenshot_interval_ms_)) { | 97 base::TimeDelta::FromMilliseconds(min_screenshot_interval_ms_)) { |
99 return; | 98 return; |
100 } | 99 } |
101 | 100 |
102 last_screenshot_time_ = now; | 101 last_screenshot_time_ = now; |
103 | 102 |
104 TakeScreenshotImpl(render_view_host, entry); | 103 TakeScreenshotImpl(render_view_host, entry); |
105 } | 104 } |
106 | 105 |
107 // Implemented here and not in NavigationEntry because this manager keeps track | 106 // Implemented here and not in NavigationEntry because this manager keeps track |
108 // of the total number of screen shots across all entries. | 107 // of the total number of screen shots across all entries. |
109 void NavigationEntryScreenshotManager::ClearAllScreenshots() { | 108 void NavigationEntryScreenshotManager::ClearAllScreenshots() { |
110 int count = owner_->GetEntryCount(); | 109 int count = owner_->GetEntryCount(); |
111 for (int i = 0; i < count; ++i) { | 110 for (int i = 0; i < count; ++i) { |
112 ClearScreenshot(NavigationEntryImpl::FromNavigationEntry( | 111 ClearScreenshot(owner_->GetEntryAtIndex(i)); |
113 owner_->GetEntryAtIndex(i))); | |
114 } | 112 } |
115 DCHECK_EQ(GetScreenshotCount(), 0); | 113 DCHECK_EQ(GetScreenshotCount(), 0); |
116 } | 114 } |
117 | 115 |
118 void NavigationEntryScreenshotManager::TakeScreenshotImpl( | 116 void NavigationEntryScreenshotManager::TakeScreenshotImpl( |
119 RenderViewHost* host, | 117 RenderViewHost* host, |
120 NavigationEntryImpl* entry) { | 118 NavigationEntryImpl* entry) { |
121 DCHECK(host && host->GetView()); | 119 DCHECK(host && host->GetView()); |
122 DCHECK(entry); | 120 DCHECK(entry); |
123 host->CopyFromBackingStore( | 121 host->CopyFromBackingStore( |
(...skipping 11 matching lines...) Expand all Loading... |
135 min_screenshot_interval_ms_ = interval_ms; | 133 min_screenshot_interval_ms_ = interval_ms; |
136 } | 134 } |
137 | 135 |
138 void NavigationEntryScreenshotManager::OnScreenshotTaken( | 136 void NavigationEntryScreenshotManager::OnScreenshotTaken( |
139 int unique_id, | 137 int unique_id, |
140 const SkBitmap& bitmap, | 138 const SkBitmap& bitmap, |
141 ReadbackResponse response) { | 139 ReadbackResponse response) { |
142 NavigationEntryImpl* entry = NULL; | 140 NavigationEntryImpl* entry = NULL; |
143 int entry_count = owner_->GetEntryCount(); | 141 int entry_count = owner_->GetEntryCount(); |
144 for (int i = 0; i < entry_count; ++i) { | 142 for (int i = 0; i < entry_count; ++i) { |
145 NavigationEntry* iter = owner_->GetEntryAtIndex(i); | 143 NavigationEntryImpl* iter = owner_->GetEntryAtIndex(i); |
146 if (iter->GetUniqueID() == unique_id) { | 144 if (iter->GetUniqueID() == unique_id) { |
147 entry = NavigationEntryImpl::FromNavigationEntry(iter); | 145 entry = iter; |
148 break; | 146 break; |
149 } | 147 } |
150 } | 148 } |
151 | 149 |
152 if (!entry) { | 150 if (!entry) { |
153 LOG(ERROR) << "Invalid entry with unique id: " << unique_id; | 151 LOG(ERROR) << "Invalid entry with unique id: " << unique_id; |
154 return; | 152 return; |
155 } | 153 } |
156 | 154 |
157 if ((response != READBACK_SUCCESS) || bitmap.empty() || bitmap.isNull()) { | 155 if ((response != READBACK_SUCCESS) || bitmap.empty() || bitmap.isNull()) { |
158 if (!ClearScreenshot(entry)) | 156 if (!ClearScreenshot(entry)) |
159 OnScreenshotSet(entry); | 157 OnScreenshotSet(entry); |
160 return; | 158 return; |
161 } | 159 } |
162 | 160 |
163 scoped_refptr<ScreenshotData> screenshot = new ScreenshotData(); | 161 scoped_refptr<ScreenshotData> screenshot = new ScreenshotData(); |
164 screenshot->EncodeScreenshot( | 162 screenshot->EncodeScreenshot( |
165 bitmap, | 163 bitmap, |
166 base::Bind(&NavigationEntryScreenshotManager::OnScreenshotEncodeComplete, | 164 base::Bind(&NavigationEntryScreenshotManager::OnScreenshotEncodeComplete, |
167 screenshot_factory_.GetWeakPtr(), | 165 screenshot_factory_.GetWeakPtr(), |
168 unique_id, | 166 unique_id, |
169 screenshot)); | 167 screenshot)); |
170 } | 168 } |
171 | 169 |
172 int NavigationEntryScreenshotManager::GetScreenshotCount() const { | 170 int NavigationEntryScreenshotManager::GetScreenshotCount() const { |
173 int screenshot_count = 0; | 171 int screenshot_count = 0; |
174 int entry_count = owner_->GetEntryCount(); | 172 int entry_count = owner_->GetEntryCount(); |
175 for (int i = 0; i < entry_count; ++i) { | 173 for (int i = 0; i < entry_count; ++i) { |
176 NavigationEntryImpl* entry = | 174 NavigationEntryImpl* entry = owner_->GetEntryAtIndex(i); |
177 NavigationEntryImpl::FromNavigationEntry(owner_->GetEntryAtIndex(i)); | |
178 if (entry->screenshot().get()) | 175 if (entry->screenshot().get()) |
179 screenshot_count++; | 176 screenshot_count++; |
180 } | 177 } |
181 return screenshot_count; | 178 return screenshot_count; |
182 } | 179 } |
183 | 180 |
184 void NavigationEntryScreenshotManager::OnScreenshotEncodeComplete( | 181 void NavigationEntryScreenshotManager::OnScreenshotEncodeComplete( |
185 int unique_id, | 182 int unique_id, |
186 scoped_refptr<ScreenshotData> screenshot) { | 183 scoped_refptr<ScreenshotData> screenshot) { |
187 NavigationEntryImpl* entry = NULL; | 184 NavigationEntryImpl* entry = NULL; |
188 int entry_count = owner_->GetEntryCount(); | 185 int entry_count = owner_->GetEntryCount(); |
189 for (int i = 0; i < entry_count; ++i) { | 186 for (int i = 0; i < entry_count; ++i) { |
190 NavigationEntry* iter = owner_->GetEntryAtIndex(i); | 187 NavigationEntryImpl* iter = owner_->GetEntryAtIndex(i); |
191 if (iter->GetUniqueID() == unique_id) { | 188 if (iter->GetUniqueID() == unique_id) { |
192 entry = NavigationEntryImpl::FromNavigationEntry(iter); | 189 entry = iter; |
193 break; | 190 break; |
194 } | 191 } |
195 } | 192 } |
196 if (!entry) | 193 if (!entry) |
197 return; | 194 return; |
198 entry->SetScreenshotPNGData(screenshot->data()); | 195 entry->SetScreenshotPNGData(screenshot->data()); |
199 OnScreenshotSet(entry); | 196 OnScreenshotSet(entry); |
200 } | 197 } |
201 | 198 |
202 void NavigationEntryScreenshotManager::OnScreenshotSet( | 199 void NavigationEntryScreenshotManager::OnScreenshotSet( |
(...skipping 14 matching lines...) Expand all Loading... |
217 void NavigationEntryScreenshotManager::PurgeScreenshotsIfNecessary() { | 214 void NavigationEntryScreenshotManager::PurgeScreenshotsIfNecessary() { |
218 // Allow only a certain number of entries to keep screenshots. | 215 // Allow only a certain number of entries to keep screenshots. |
219 const int kMaxScreenshots = 10; | 216 const int kMaxScreenshots = 10; |
220 int screenshot_count = GetScreenshotCount(); | 217 int screenshot_count = GetScreenshotCount(); |
221 if (screenshot_count < kMaxScreenshots) | 218 if (screenshot_count < kMaxScreenshots) |
222 return; | 219 return; |
223 | 220 |
224 const int current = owner_->GetCurrentEntryIndex(); | 221 const int current = owner_->GetCurrentEntryIndex(); |
225 const int num_entries = owner_->GetEntryCount(); | 222 const int num_entries = owner_->GetEntryCount(); |
226 int available_slots = kMaxScreenshots; | 223 int available_slots = kMaxScreenshots; |
227 if (NavigationEntryImpl::FromNavigationEntry(owner_->GetEntryAtIndex(current)) | 224 if (owner_->GetEntryAtIndex(current)->screenshot().get()) { |
228 ->screenshot().get()) { | |
229 --available_slots; | 225 --available_slots; |
230 } | 226 } |
231 | 227 |
232 // Keep screenshots closer to the current navigation entry, and purge the ones | 228 // Keep screenshots closer to the current navigation entry, and purge the ones |
233 // that are farther away from it. So in each step, look at the entries at | 229 // that are farther away from it. So in each step, look at the entries at |
234 // each offset on both the back and forward history, and start counting them | 230 // each offset on both the back and forward history, and start counting them |
235 // to make sure that the correct number of screenshots are kept in memory. | 231 // to make sure that the correct number of screenshots are kept in memory. |
236 // Note that it is possible for some entries to be missing screenshots (e.g. | 232 // Note that it is possible for some entries to be missing screenshots (e.g. |
237 // when taking the screenshot failed for some reason). So there may be a state | 233 // when taking the screenshot failed for some reason). So there may be a state |
238 // where there are a lot of entries in the back history, but none of them has | 234 // where there are a lot of entries in the back history, but none of them has |
239 // any screenshot. In such cases, keep the screenshots for |kMaxScreenshots| | 235 // any screenshot. In such cases, keep the screenshots for |kMaxScreenshots| |
240 // entries in the forward history list. | 236 // entries in the forward history list. |
241 int back = current - 1; | 237 int back = current - 1; |
242 int forward = current + 1; | 238 int forward = current + 1; |
243 while (available_slots > 0 && (back >= 0 || forward < num_entries)) { | 239 while (available_slots > 0 && (back >= 0 || forward < num_entries)) { |
244 if (back >= 0) { | 240 if (back >= 0) { |
245 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( | 241 NavigationEntryImpl* entry = owner_->GetEntryAtIndex(back); |
246 owner_->GetEntryAtIndex(back)); | |
247 if (entry->screenshot().get()) | 242 if (entry->screenshot().get()) |
248 --available_slots; | 243 --available_slots; |
249 --back; | 244 --back; |
250 } | 245 } |
251 | 246 |
252 if (available_slots > 0 && forward < num_entries) { | 247 if (available_slots > 0 && forward < num_entries) { |
253 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( | 248 NavigationEntryImpl* entry = owner_->GetEntryAtIndex(forward); |
254 owner_->GetEntryAtIndex(forward)); | |
255 if (entry->screenshot().get()) | 249 if (entry->screenshot().get()) |
256 --available_slots; | 250 --available_slots; |
257 ++forward; | 251 ++forward; |
258 } | 252 } |
259 } | 253 } |
260 | 254 |
261 // Purge any screenshot at |back| or lower indices, and |forward| or higher | 255 // Purge any screenshot at |back| or lower indices, and |forward| or higher |
262 // indices. | 256 // indices. |
263 while (screenshot_count > kMaxScreenshots && back >= 0) { | 257 while (screenshot_count > kMaxScreenshots && back >= 0) { |
264 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( | 258 NavigationEntryImpl* entry = owner_->GetEntryAtIndex(back); |
265 owner_->GetEntryAtIndex(back)); | |
266 if (ClearScreenshot(entry)) | 259 if (ClearScreenshot(entry)) |
267 --screenshot_count; | 260 --screenshot_count; |
268 --back; | 261 --back; |
269 } | 262 } |
270 | 263 |
271 while (screenshot_count > kMaxScreenshots && forward < num_entries) { | 264 while (screenshot_count > kMaxScreenshots && forward < num_entries) { |
272 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( | 265 NavigationEntryImpl* entry = owner_->GetEntryAtIndex(forward); |
273 owner_->GetEntryAtIndex(forward)); | |
274 if (ClearScreenshot(entry)) | 266 if (ClearScreenshot(entry)) |
275 --screenshot_count; | 267 --screenshot_count; |
276 ++forward; | 268 ++forward; |
277 } | 269 } |
278 CHECK_GE(screenshot_count, 0); | 270 CHECK_GE(screenshot_count, 0); |
279 CHECK_LE(screenshot_count, kMaxScreenshots); | 271 CHECK_LE(screenshot_count, kMaxScreenshots); |
280 } | 272 } |
281 | 273 |
282 } // namespace content | 274 } // namespace content |
OLD | NEW |