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" |
11 #include "content/browser/renderer_host/render_view_host_impl.h" | 11 #include "content/browser/renderer_host/render_view_host_impl.h" |
12 #include "content/public/browser/render_widget_host.h" | 12 #include "content/public/browser/render_widget_host.h" |
13 #include "content/public/browser/render_widget_host_view.h" | 13 #include "content/public/browser/render_widget_host_view.h" |
14 #include "content/public/browser/site_instance.h" | |
14 #include "content/public/common/content_switches.h" | 15 #include "content/public/common/content_switches.h" |
15 #include "third_party/skia/include/core/SkCanvas.h" | 16 #include "third_party/skia/include/core/SkCanvas.h" |
16 #include "third_party/skia/include/core/SkPaint.h" | 17 #include "third_party/skia/include/core/SkPaint.h" |
17 #include "third_party/skia/include/effects/SkLumaColorFilter.h" | 18 #include "third_party/skia/include/effects/SkLumaColorFilter.h" |
18 #include "ui/gfx/codec/png_codec.h" | 19 #include "ui/gfx/codec/png_codec.h" |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 // Minimum delay between taking screenshots. | 23 // Minimum delay between taking screenshots. |
23 const int kMinScreenshotIntervalMS = 1000; | 24 const int kMinScreenshotIntervalMS = 1000; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 // Encode the a8Bitmap to grayscale PNG treating alpha as color intensity | 69 // Encode the a8Bitmap to grayscale PNG treating alpha as color intensity |
69 if (gfx::PNGCodec::EncodeA8SkBitmap(a8Bitmap, &data)) | 70 if (gfx::PNGCodec::EncodeA8SkBitmap(a8Bitmap, &data)) |
70 data_ = new base::RefCountedBytes(data); | 71 data_ = new base::RefCountedBytes(data); |
71 } | 72 } |
72 | 73 |
73 scoped_refptr<base::RefCountedBytes> data_; | 74 scoped_refptr<base::RefCountedBytes> data_; |
74 | 75 |
75 DISALLOW_COPY_AND_ASSIGN(ScreenshotData); | 76 DISALLOW_COPY_AND_ASSIGN(ScreenshotData); |
76 }; | 77 }; |
77 | 78 |
79 // A temporary solution to keep a RenderViewHost and SiteInstanceImpl live | |
Charlie Reis
2014/02/20 19:01:53
Please add a TODO saying when this can be removed
sadrul
2014/02/21 03:51:16
Done (is there a crbug I can reference from the TO
| |
80 // (after cross-process/cross-site navigation) for long enough to get the | |
81 // screenshot. | |
82 class SiteInstanceKeepAlive { | |
83 public: | |
84 explicit SiteInstanceKeepAlive(scoped_refptr<SiteInstanceImpl> instance) | |
85 : instance_(instance) { | |
86 instance_->increment_active_view_count(); | |
87 instance_->GetProcess()->AddPendingView(); | |
88 } | |
89 | |
90 ~SiteInstanceKeepAlive() { | |
91 instance_->GetProcess()->RemovePendingView(); | |
92 instance_->decrement_active_view_count(); | |
sadrul
2014/02/20 05:13:31
Do we need to do anything here to make sure the Si
Charlie Reis
2014/02/20 19:01:53
Those methods don't do anything on their own, so y
sadrul
2014/02/21 03:51:16
I have exposed RenderFrameHostManager::ShutdownRen
| |
93 } | |
94 | |
95 private: | |
96 scoped_refptr<SiteInstanceImpl> instance_; | |
97 | |
98 DISALLOW_COPY_AND_ASSIGN(SiteInstanceKeepAlive); | |
99 }; | |
100 | |
78 NavigationEntryScreenshotManager::NavigationEntryScreenshotManager( | 101 NavigationEntryScreenshotManager::NavigationEntryScreenshotManager( |
79 NavigationControllerImpl* owner) | 102 NavigationControllerImpl* owner) |
80 : owner_(owner), | 103 : owner_(owner), |
81 screenshot_factory_(this), | 104 screenshot_factory_(this), |
82 min_screenshot_interval_ms_(kMinScreenshotIntervalMS) { | 105 min_screenshot_interval_ms_(kMinScreenshotIntervalMS) { |
83 } | 106 } |
84 | 107 |
85 NavigationEntryScreenshotManager::~NavigationEntryScreenshotManager() { | 108 NavigationEntryScreenshotManager::~NavigationEntryScreenshotManager() { |
86 } | 109 } |
87 | 110 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 owner_->GetEntryAtIndex(i))); | 150 owner_->GetEntryAtIndex(i))); |
128 } | 151 } |
129 DCHECK_EQ(GetScreenshotCount(), 0); | 152 DCHECK_EQ(GetScreenshotCount(), 0); |
130 } | 153 } |
131 | 154 |
132 void NavigationEntryScreenshotManager::TakeScreenshotImpl( | 155 void NavigationEntryScreenshotManager::TakeScreenshotImpl( |
133 RenderViewHost* host, | 156 RenderViewHost* host, |
134 NavigationEntryImpl* entry) { | 157 NavigationEntryImpl* entry) { |
135 DCHECK(host && host->GetView()); | 158 DCHECK(host && host->GetView()); |
136 DCHECK(entry); | 159 DCHECK(entry); |
160 scoped_refptr<SiteInstanceImpl> site_instance( | |
161 static_cast<SiteInstanceImpl*>(host->GetSiteInstance())); | |
162 scoped_ptr<SiteInstanceKeepAlive> keep_alive( | |
163 new SiteInstanceKeepAlive(site_instance)); | |
137 host->CopyFromBackingStore(gfx::Rect(), | 164 host->CopyFromBackingStore(gfx::Rect(), |
138 host->GetView()->GetViewBounds().size(), | 165 host->GetView()->GetViewBounds().size(), |
139 base::Bind(&NavigationEntryScreenshotManager::OnScreenshotTaken, | 166 base::Bind(&NavigationEntryScreenshotManager::OnScreenshotTaken, |
Charlie Reis
2014/02/20 19:01:53
What happens if we never make it to OnScreenshotTa
sadrul
2014/02/21 03:51:16
CopyFromBackingStore callback is guaranteed to be
| |
140 screenshot_factory_.GetWeakPtr(), | 167 screenshot_factory_.GetWeakPtr(), |
141 entry->GetUniqueID())); | 168 entry->GetUniqueID(), |
169 base::Passed(&keep_alive))); | |
Charlie Reis
2014/02/20 19:01:53
Albert, can I get your eyes on this?
awong
2014/02/20 22:44:31
Seems legit, but using a raw pointer (as in the la
sadrul
2014/02/21 03:51:16
I have changed the way the keep-alive object is se
| |
142 } | 170 } |
143 | 171 |
144 void NavigationEntryScreenshotManager::SetMinScreenshotIntervalMS( | 172 void NavigationEntryScreenshotManager::SetMinScreenshotIntervalMS( |
145 int interval_ms) { | 173 int interval_ms) { |
146 DCHECK_GE(interval_ms, 0); | 174 DCHECK_GE(interval_ms, 0); |
147 min_screenshot_interval_ms_ = interval_ms; | 175 min_screenshot_interval_ms_ = interval_ms; |
148 } | 176 } |
149 | 177 |
150 void NavigationEntryScreenshotManager::OnScreenshotTaken(int unique_id, | 178 void NavigationEntryScreenshotManager::OnScreenshotTaken( |
151 bool success, | 179 int unique_id, |
152 const SkBitmap& bitmap) { | 180 scoped_ptr<SiteInstanceKeepAlive> keep_alive, |
181 bool success, | |
182 const SkBitmap& bitmap) { | |
153 NavigationEntryImpl* entry = NULL; | 183 NavigationEntryImpl* entry = NULL; |
154 int entry_count = owner_->GetEntryCount(); | 184 int entry_count = owner_->GetEntryCount(); |
155 for (int i = 0; i < entry_count; ++i) { | 185 for (int i = 0; i < entry_count; ++i) { |
156 NavigationEntry* iter = owner_->GetEntryAtIndex(i); | 186 NavigationEntry* iter = owner_->GetEntryAtIndex(i); |
157 if (iter->GetUniqueID() == unique_id) { | 187 if (iter->GetUniqueID() == unique_id) { |
158 entry = NavigationEntryImpl::FromNavigationEntry(iter); | 188 entry = NavigationEntryImpl::FromNavigationEntry(iter); |
159 break; | 189 break; |
160 } | 190 } |
161 } | 191 } |
162 | 192 |
163 if (!entry) { | 193 if (!entry) { |
164 LOG(ERROR) << "Invalid entry with unique id: " << unique_id; | 194 LOG(ERROR) << "Invalid entry with unique id: " << unique_id; |
165 return; | 195 return; |
166 } | 196 } |
167 | 197 |
168 if (!success || bitmap.empty() || bitmap.isNull()) { | 198 if (!success || bitmap.empty() || bitmap.isNull()) { |
169 if (!ClearScreenshot(entry)) | 199 if (!ClearScreenshot(entry)) |
170 OnScreenshotSet(entry); | 200 OnScreenshotSet(entry); |
mfomitchev
2014/02/20 19:15:48
We should get rid of this and just have ClearScree
sadrul
2014/02/21 03:51:16
Done.
| |
171 return; | 201 return; |
172 } | 202 } |
173 | 203 |
174 scoped_refptr<ScreenshotData> screenshot = new ScreenshotData(); | 204 scoped_refptr<ScreenshotData> screenshot = new ScreenshotData(); |
175 screenshot->EncodeScreenshot( | 205 screenshot->EncodeScreenshot( |
176 bitmap, | 206 bitmap, |
177 base::Bind(&NavigationEntryScreenshotManager::OnScreenshotEncodeComplete, | 207 base::Bind(&NavigationEntryScreenshotManager::OnScreenshotEncodeComplete, |
178 screenshot_factory_.GetWeakPtr(), | 208 screenshot_factory_.GetWeakPtr(), |
179 unique_id, | 209 unique_id, |
180 screenshot)); | 210 screenshot)); |
181 } | 211 } |
182 | 212 |
213 void NavigationEntryScreenshotManager::OnScreenshotTakenInTest( | |
214 int unique_id, | |
215 bool success, | |
216 const SkBitmap& bitmap) { | |
217 OnScreenshotTaken(unique_id, scoped_ptr<SiteInstanceKeepAlive>(), success, | |
218 bitmap); | |
219 } | |
220 | |
183 int NavigationEntryScreenshotManager::GetScreenshotCount() const { | 221 int NavigationEntryScreenshotManager::GetScreenshotCount() const { |
184 int screenshot_count = 0; | 222 int screenshot_count = 0; |
185 int entry_count = owner_->GetEntryCount(); | 223 int entry_count = owner_->GetEntryCount(); |
186 for (int i = 0; i < entry_count; ++i) { | 224 for (int i = 0; i < entry_count; ++i) { |
187 NavigationEntryImpl* entry = | 225 NavigationEntryImpl* entry = |
188 NavigationEntryImpl::FromNavigationEntry(owner_->GetEntryAtIndex(i)); | 226 NavigationEntryImpl::FromNavigationEntry(owner_->GetEntryAtIndex(i)); |
189 if (entry->screenshot().get()) | 227 if (entry->screenshot().get()) |
190 screenshot_count++; | 228 screenshot_count++; |
191 } | 229 } |
192 return screenshot_count; | 230 return screenshot_count; |
(...skipping 12 matching lines...) Expand all Loading... | |
205 } | 243 } |
206 } | 244 } |
207 if (!entry) | 245 if (!entry) |
208 return; | 246 return; |
209 entry->SetScreenshotPNGData(screenshot->data()); | 247 entry->SetScreenshotPNGData(screenshot->data()); |
210 OnScreenshotSet(entry); | 248 OnScreenshotSet(entry); |
211 } | 249 } |
212 | 250 |
213 void NavigationEntryScreenshotManager::OnScreenshotSet( | 251 void NavigationEntryScreenshotManager::OnScreenshotSet( |
214 NavigationEntryImpl* entry) { | 252 NavigationEntryImpl* entry) { |
215 if (entry->screenshot().get()) | 253 if (entry->screenshot().get()) |
mfomitchev
2014/02/20 19:15:48
I think this check is unnecessary if we make the f
sadrul
2014/02/21 03:51:16
Done.
| |
216 PurgeScreenshotsIfNecessary(); | 254 PurgeScreenshotsIfNecessary(); |
217 } | 255 } |
218 | 256 |
219 bool NavigationEntryScreenshotManager::ClearScreenshot( | 257 bool NavigationEntryScreenshotManager::ClearScreenshot( |
220 NavigationEntryImpl* entry) { | 258 NavigationEntryImpl* entry) { |
221 if (!entry->screenshot().get()) | 259 if (!entry->screenshot().get()) |
222 return false; | 260 return false; |
223 | 261 |
224 entry->SetScreenshotPNGData(NULL); | 262 entry->SetScreenshotPNGData(NULL); |
225 return true; | 263 return true; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 owner_->GetEntryAtIndex(forward)); | 322 owner_->GetEntryAtIndex(forward)); |
285 if (ClearScreenshot(entry)) | 323 if (ClearScreenshot(entry)) |
286 --screenshot_count; | 324 --screenshot_count; |
287 ++forward; | 325 ++forward; |
288 } | 326 } |
289 CHECK_GE(screenshot_count, 0); | 327 CHECK_GE(screenshot_count, 0); |
290 CHECK_LE(screenshot_count, kMaxScreenshots); | 328 CHECK_LE(screenshot_count, kMaxScreenshots); |
291 } | 329 } |
292 | 330 |
293 } // namespace content | 331 } // namespace content |
OLD | NEW |