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 "chrome/browser/media/native_desktop_media_list.h" | 5 #include "chrome/browser/media/native_desktop_media_list.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <map> | 9 #include <map> |
10 #include <set> | 10 #include <set> |
11 #include <sstream> | 11 #include <sstream> |
12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> |
13 | 14 |
14 #include "base/hash.h" | 15 #include "base/hash.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/macros.h" | 17 #include "base/macros.h" |
17 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
18 #include "base/threading/sequenced_worker_pool.h" | 19 #include "base/threading/sequenced_worker_pool.h" |
| 20 #include "chrome/browser/mac/bluetooth_utility.h" |
19 #include "chrome/browser/media/desktop_media_list_observer.h" | 21 #include "chrome/browser/media/desktop_media_list_observer.h" |
| 22 #include "chrome/browser/profiles/profile_manager.h" |
| 23 #include "chrome/browser/ui/browser.h" |
| 24 #include "chrome/browser/ui/browser_iterator.h" |
| 25 #include "chrome/browser/ui/host_desktop.h" |
| 26 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
20 #include "chrome/grit/generated_resources.h" | 27 #include "chrome/grit/generated_resources.h" |
| 28 #include "components/favicon/content/content_favicon_driver.h" |
21 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 30 #include "content/public/browser/render_frame_host.h" |
| 31 #include "content/public/browser/render_process_host.h" |
22 #include "media/base/video_util.h" | 32 #include "media/base/video_util.h" |
23 #include "third_party/libyuv/include/libyuv/scale_argb.h" | 33 #include "third_party/libyuv/include/libyuv/scale_argb.h" |
24 #include "third_party/skia/include/core/SkBitmap.h" | 34 #include "third_party/skia/include/core/SkBitmap.h" |
25 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 35 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
26 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" | 36 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" |
27 #include "third_party/webrtc/modules/desktop_capture/window_capturer.h" | 37 #include "third_party/webrtc/modules/desktop_capture/window_capturer.h" |
| 38 #include "ui/aura/window.h" |
28 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
29 #include "ui/gfx/skia_util.h" | 40 #include "ui/gfx/skia_util.h" |
| 41 #include "ui/snapshot/snapshot.h" |
30 | 42 |
31 using content::BrowserThread; | 43 using content::BrowserThread; |
32 using content::DesktopMediaID; | 44 using content::DesktopMediaID; |
33 | 45 |
34 namespace { | 46 namespace { |
35 | 47 |
36 // Update the list every second. | 48 // Update the list every second. |
37 const int kDefaultUpdatePeriod = 1000; | 49 const int kDefaultUpdatePeriod = 1000; |
38 | 50 |
39 // Returns a hash of a DesktopFrame content to detect when image for a desktop | 51 // Returns a hash of a DesktopFrame content to detect when image for a desktop |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 result.unlockPixels(); | 87 result.unlockPixels(); |
76 | 88 |
77 return gfx::ImageSkia::CreateFrom1xBitmap(result); | 89 return gfx::ImageSkia::CreateFrom1xBitmap(result); |
78 } | 90 } |
79 | 91 |
80 } // namespace | 92 } // namespace |
81 | 93 |
82 NativeDesktopMediaList::SourceDescription::SourceDescription( | 94 NativeDesktopMediaList::SourceDescription::SourceDescription( |
83 DesktopMediaID id, | 95 DesktopMediaID id, |
84 const base::string16& name) | 96 const base::string16& name) |
85 : id(id), | 97 : id(id), name(name) {} |
86 name(name) { | |
87 } | |
88 | 98 |
89 class NativeDesktopMediaList::Worker | 99 class NativeDesktopMediaList::Worker |
90 : public webrtc::DesktopCapturer::Callback { | 100 : public webrtc::DesktopCapturer::Callback { |
91 public: | 101 public: |
92 Worker(base::WeakPtr<NativeDesktopMediaList> media_list, | 102 Worker(base::WeakPtr<NativeDesktopMediaList> media_list, |
93 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, | 103 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, |
94 scoped_ptr<webrtc::WindowCapturer> window_capturer); | 104 scoped_ptr<webrtc::WindowCapturer> window_capturer); |
95 ~Worker() override; | 105 ~Worker() override; |
96 | 106 |
97 void Refresh(const gfx::Size& thumbnail_size, | 107 void Refresh(const gfx::Size& thumbnail_size, |
98 content::DesktopMediaID::Id view_dialog_id); | 108 content::DesktopMediaID::Id view_dialog_id, |
| 109 const std::vector<SourceDescription>& tab_sources); |
99 | 110 |
100 private: | 111 private: |
101 typedef std::map<DesktopMediaID, uint32_t> ImageHashesMap; | 112 typedef std::map<DesktopMediaID, uint32_t> ImageHashesMap; |
102 | 113 |
103 // webrtc::DesktopCapturer::Callback interface. | 114 // webrtc::DesktopCapturer::Callback interface. |
104 webrtc::SharedMemory* CreateSharedMemory(size_t size) override; | 115 webrtc::SharedMemory* CreateSharedMemory(size_t size) override; |
105 void OnCaptureCompleted(webrtc::DesktopFrame* frame) override; | 116 void OnCaptureCompleted(webrtc::DesktopFrame* frame) override; |
106 | 117 |
107 base::WeakPtr<NativeDesktopMediaList> media_list_; | 118 base::WeakPtr<NativeDesktopMediaList> media_list_; |
108 | 119 |
(...skipping 17 matching lines...) Expand all Loading... |
126 if (screen_capturer_) | 137 if (screen_capturer_) |
127 screen_capturer_->Start(this); | 138 screen_capturer_->Start(this); |
128 if (window_capturer_) | 139 if (window_capturer_) |
129 window_capturer_->Start(this); | 140 window_capturer_->Start(this); |
130 } | 141 } |
131 | 142 |
132 NativeDesktopMediaList::Worker::~Worker() {} | 143 NativeDesktopMediaList::Worker::~Worker() {} |
133 | 144 |
134 void NativeDesktopMediaList::Worker::Refresh( | 145 void NativeDesktopMediaList::Worker::Refresh( |
135 const gfx::Size& thumbnail_size, | 146 const gfx::Size& thumbnail_size, |
136 content::DesktopMediaID::Id view_dialog_id) { | 147 content::DesktopMediaID::Id view_dialog_id, |
| 148 const std::vector<SourceDescription>& tab_sources) { |
137 std::vector<SourceDescription> sources; | 149 std::vector<SourceDescription> sources; |
138 | 150 |
139 if (screen_capturer_) { | 151 if (screen_capturer_) { |
140 webrtc::ScreenCapturer::ScreenList screens; | 152 webrtc::ScreenCapturer::ScreenList screens; |
141 if (screen_capturer_->GetScreenList(&screens)) { | 153 if (screen_capturer_->GetScreenList(&screens)) { |
142 bool mutiple_screens = screens.size() > 1; | 154 bool mutiple_screens = screens.size() > 1; |
143 base::string16 title; | 155 base::string16 title; |
144 for (size_t i = 0; i < screens.size(); ++i) { | 156 for (size_t i = 0; i < screens.size(); ++i) { |
145 if (mutiple_screens) { | 157 if (mutiple_screens) { |
146 title = l10n_util::GetStringFUTF16Int( | 158 title = l10n_util::GetStringFUTF16Int( |
(...skipping 16 matching lines...) Expand all Loading... |
163 it != windows.end(); ++it) { | 175 it != windows.end(); ++it) { |
164 // Skip the picker dialog window. | 176 // Skip the picker dialog window. |
165 if (it->id != view_dialog_id) { | 177 if (it->id != view_dialog_id) { |
166 sources.push_back(SourceDescription( | 178 sources.push_back(SourceDescription( |
167 DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id), | 179 DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id), |
168 base::UTF8ToUTF16(it->title))); | 180 base::UTF8ToUTF16(it->title))); |
169 } | 181 } |
170 } | 182 } |
171 } | 183 } |
172 } | 184 } |
| 185 |
| 186 // Add tab sources to all media sources. |
| 187 sources.insert(sources.end(), tab_sources.begin(), tab_sources.end()); |
| 188 |
173 // Update list of windows before updating thumbnails. | 189 // Update list of windows before updating thumbnails. |
174 BrowserThread::PostTask( | 190 BrowserThread::PostTask( |
175 BrowserThread::UI, FROM_HERE, | 191 BrowserThread::UI, FROM_HERE, |
176 base::Bind(&NativeDesktopMediaList::OnSourcesList, | 192 base::Bind(&NativeDesktopMediaList::OnSourcesList, |
177 media_list_, sources)); | 193 media_list_, sources)); |
178 | 194 |
179 ImageHashesMap new_image_hashes; | 195 ImageHashesMap new_image_hashes; |
180 | 196 |
181 // Get a thumbnail for each source. | 197 // Get a thumbnail for each source. |
182 for (size_t i = 0; i < sources.size(); ++i) { | 198 for (size_t i = 0; i < sources.size(); ++i) { |
183 SourceDescription& source = sources[i]; | 199 SourceDescription& source = sources[i]; |
184 switch (source.id.type) { | 200 switch (source.id.type) { |
185 case DesktopMediaID::TYPE_SCREEN: | 201 case DesktopMediaID::TYPE_SCREEN: |
186 if (!screen_capturer_->SelectScreen(source.id.id)) | 202 if (!screen_capturer_->SelectScreen(source.id.id)) |
187 continue; | 203 continue; |
188 screen_capturer_->Capture(webrtc::DesktopRegion()); | 204 screen_capturer_->Capture(webrtc::DesktopRegion()); |
189 break; | 205 break; |
190 | 206 |
191 case DesktopMediaID::TYPE_WINDOW: | 207 case DesktopMediaID::TYPE_WINDOW: |
192 if (!window_capturer_->SelectWindow(source.id.id)) | 208 if (!window_capturer_->SelectWindow(source.id.id)) |
193 continue; | 209 continue; |
194 window_capturer_->Capture(webrtc::DesktopRegion()); | 210 window_capturer_->Capture(webrtc::DesktopRegion()); |
195 break; | 211 break; |
| 212 case DesktopMediaID::TYPE_TAB: |
| 213 // Favicon has already captured for tabs. |
| 214 break; |
196 | 215 |
197 default: | 216 default: |
198 NOTREACHED(); | 217 NOTREACHED(); |
199 } | 218 } |
200 | 219 |
| 220 // Use captured tab favicon as thumbnail. |
| 221 if (source.id.type == DesktopMediaID::TYPE_TAB) { |
| 222 BrowserThread::PostTask( |
| 223 BrowserThread::UI, FROM_HERE, |
| 224 base::Bind(&NativeDesktopMediaList::OnSourceTabThumbnail, media_list_, |
| 225 source)); |
| 226 continue; |
| 227 } |
| 228 |
201 // Expect that DesktopCapturer to always captures frames synchronously. | 229 // Expect that DesktopCapturer to always captures frames synchronously. |
202 // |current_frame_| may be NULL if capture failed (e.g. because window has | 230 // |current_frame_| may be NULL if capture failed (e.g. because window has |
203 // been closed). | 231 // been closed). |
204 if (current_frame_) { | 232 if (current_frame_) { |
205 uint32_t frame_hash = GetFrameHash(current_frame_.get()); | 233 uint32_t frame_hash = GetFrameHash(current_frame_.get()); |
206 new_image_hashes[source.id] = frame_hash; | 234 new_image_hashes[source.id] = frame_hash; |
207 | 235 |
208 // Scale the image only if it has changed. | 236 // Scale the image only if it has changed. |
209 ImageHashesMap::iterator it = image_hashes_.find(source.id); | 237 ImageHashesMap::iterator it = image_hashes_.find(source.id); |
210 if (it == image_hashes_.end() || it->second != frame_hash) { | 238 if (it == image_hashes_.end() || it->second != frame_hash) { |
211 gfx::ImageSkia thumbnail = | 239 gfx::ImageSkia thumbnail = |
212 ScaleDesktopFrame(std::move(current_frame_), thumbnail_size); | 240 ScaleDesktopFrame(std::move(current_frame_), thumbnail_size); |
213 BrowserThread::PostTask( | 241 BrowserThread::PostTask( |
214 BrowserThread::UI, FROM_HERE, | 242 BrowserThread::UI, FROM_HERE, |
215 base::Bind(&NativeDesktopMediaList::OnSourceThumbnail, | 243 base::Bind(&NativeDesktopMediaList::OnSourceThumbnail, media_list_, |
216 media_list_, i, thumbnail)); | 244 i, thumbnail)); |
217 } | 245 } |
218 } | 246 } |
219 } | 247 } |
220 | 248 |
221 image_hashes_.swap(new_image_hashes); | 249 image_hashes_.swap(new_image_hashes); |
222 | 250 |
223 BrowserThread::PostTask( | 251 BrowserThread::PostTask( |
224 BrowserThread::UI, FROM_HERE, | 252 BrowserThread::UI, FROM_HERE, |
225 base::Bind(&NativeDesktopMediaList::OnRefreshFinished, media_list_)); | 253 base::Bind(&NativeDesktopMediaList::OnRefreshFinished, media_list_)); |
226 } | 254 } |
227 | 255 |
228 webrtc::SharedMemory* NativeDesktopMediaList::Worker::CreateSharedMemory( | 256 webrtc::SharedMemory* NativeDesktopMediaList::Worker::CreateSharedMemory( |
229 size_t size) { | 257 size_t size) { |
230 return NULL; | 258 return NULL; |
231 } | 259 } |
232 | 260 |
233 void NativeDesktopMediaList::Worker::OnCaptureCompleted( | 261 void NativeDesktopMediaList::Worker::OnCaptureCompleted( |
234 webrtc::DesktopFrame* frame) { | 262 webrtc::DesktopFrame* frame) { |
235 current_frame_.reset(frame); | 263 current_frame_.reset(frame); |
236 } | 264 } |
237 | 265 |
238 NativeDesktopMediaList::NativeDesktopMediaList( | 266 NativeDesktopMediaList::NativeDesktopMediaList( |
239 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, | 267 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, |
240 scoped_ptr<webrtc::WindowCapturer> window_capturer) | 268 scoped_ptr<webrtc::WindowCapturer> window_capturer, |
| 269 bool tab_capture_enabled) |
241 : screen_capturer_(std::move(screen_capturer)), | 270 : screen_capturer_(std::move(screen_capturer)), |
242 window_capturer_(std::move(window_capturer)), | 271 window_capturer_(std::move(window_capturer)), |
| 272 tab_capture_enabled_(tab_capture_enabled), |
243 update_period_(base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)), | 273 update_period_(base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)), |
244 thumbnail_size_(100, 100), | 274 thumbnail_size_(100, 100), |
245 view_dialog_id_(content::DesktopMediaID::TYPE_NONE, -1), | 275 view_dialog_id_(content::DesktopMediaID::TYPE_NONE, -1), |
246 observer_(NULL), | 276 observer_(NULL), |
247 weak_factory_(this) { | 277 weak_factory_(this) { |
248 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool(); | 278 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool(); |
249 capture_task_runner_ = worker_pool->GetSequencedTaskRunner( | 279 capture_task_runner_ = worker_pool->GetSequencedTaskRunner( |
250 worker_pool->GetSequenceToken()); | 280 worker_pool->GetSequenceToken()); |
251 } | 281 } |
252 | 282 |
(...skipping 11 matching lines...) Expand all Loading... |
264 thumbnail_size_ = thumbnail_size; | 294 thumbnail_size_ = thumbnail_size; |
265 } | 295 } |
266 | 296 |
267 void NativeDesktopMediaList::SetViewDialogWindowId( | 297 void NativeDesktopMediaList::SetViewDialogWindowId( |
268 content::DesktopMediaID dialog_id) { | 298 content::DesktopMediaID dialog_id) { |
269 view_dialog_id_ = dialog_id; | 299 view_dialog_id_ = dialog_id; |
270 } | 300 } |
271 | 301 |
272 void NativeDesktopMediaList::StartUpdating(DesktopMediaListObserver* observer) { | 302 void NativeDesktopMediaList::StartUpdating(DesktopMediaListObserver* observer) { |
273 DCHECK(!observer_); | 303 DCHECK(!observer_); |
274 DCHECK(screen_capturer_ || window_capturer_); | 304 DCHECK(screen_capturer_ || window_capturer_ || tab_capture_enabled_); |
275 | 305 |
276 observer_ = observer; | 306 observer_ = observer; |
277 | 307 |
278 worker_.reset(new Worker(weak_factory_.GetWeakPtr(), | 308 worker_.reset(new Worker(weak_factory_.GetWeakPtr(), |
279 std::move(screen_capturer_), | 309 std::move(screen_capturer_), |
280 std::move(window_capturer_))); | 310 std::move(window_capturer_))); |
281 Refresh(); | 311 Refresh(); |
282 } | 312 } |
283 | 313 |
284 int NativeDesktopMediaList::GetSourceCount() const { | 314 int NativeDesktopMediaList::GetSourceCount() const { |
285 return sources_.size(); | 315 return sources_.size(); |
286 } | 316 } |
287 | 317 |
288 const DesktopMediaList::Source& NativeDesktopMediaList::GetSource( | 318 const DesktopMediaList::Source& NativeDesktopMediaList::GetSource( |
289 int index) const { | 319 int index) const { |
290 return sources_[index]; | 320 return sources_[index]; |
291 } | 321 } |
292 | 322 |
293 void NativeDesktopMediaList::Refresh() { | 323 void NativeDesktopMediaList::Refresh() { |
| 324 // Get tab source list. |
| 325 std::vector<SourceDescription> tab_sources; |
| 326 if (tab_capture_enabled_) |
| 327 GetTabSourceDescriptions(&tab_sources); |
| 328 |
294 capture_task_runner_->PostTask( | 329 capture_task_runner_->PostTask( |
295 FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), | 330 FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), |
296 thumbnail_size_, view_dialog_id_.id)); | 331 thumbnail_size_, view_dialog_id_.id, tab_sources)); |
| 332 } |
| 333 |
| 334 void NativeDesktopMediaList::GetTabSourceDescriptions( |
| 335 std::vector<SourceDescription>* tab_sources) { |
| 336 // Clear old favicon map. |
| 337 tab_icon_map_.clear(); |
| 338 |
| 339 // Use to sort tabs based on their last active time stamps. |
| 340 std::map<base::TimeTicks, SourceDescription> tab_map; |
| 341 |
| 342 // Enumerate all tabs with their titles and favicons for a user profile. |
| 343 Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); |
| 344 std::vector<Browser*> browsers; |
| 345 for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
| 346 if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile()) |
| 347 browsers.push_back(*it); |
| 348 } |
| 349 |
| 350 for (auto browser : browsers) { |
| 351 TabStripModel* tab_strip_model = browser->tab_strip_model(); |
| 352 DCHECK(tab_strip_model); |
| 353 |
| 354 for (int i = 0; i < tab_strip_model->count(); i++) { |
| 355 content::WebContents* contents = tab_strip_model->GetWebContentsAt(i); |
| 356 content::RenderFrameHost* const main_frame = contents->GetMainFrame(); |
| 357 DCHECK(main_frame); |
| 358 DesktopMediaID media_id( |
| 359 DesktopMediaID::TYPE_TAB, DesktopMediaID::kNullId, |
| 360 content::WebContentsMediaCaptureId(main_frame->GetProcess()->GetID(), |
| 361 main_frame->GetRoutingID())); |
| 362 |
| 363 // Create display tab title. |
| 364 base::string16 title = l10n_util::GetStringFUTF16( |
| 365 IDS_DESKTOP_MEDIA_PICKER_CHROME_TAB_TITLE, contents->GetTitle()); |
| 366 |
| 367 // Create thumbnail based on favicon for tab. |
| 368 favicon::FaviconDriver* favicon_driver = |
| 369 favicon::ContentFaviconDriver::FromWebContents(contents); |
| 370 if (favicon_driver) { |
| 371 gfx::Image tab_icon = favicon_driver->GetFavicon(); |
| 372 tab_icon_map_[std::pair<int, int>( |
| 373 media_id.tab_id.render_process_id, |
| 374 media_id.tab_id.main_render_frame_id)] = |
| 375 CreateEnlargedFaviconImage(thumbnail_size_, tab_icon); |
| 376 } |
| 377 |
| 378 // Get tab's last active time stamp. |
| 379 base::TimeTicks t = contents->GetLastActiveTime(); |
| 380 tab_map.insert(std::make_pair(t, SourceDescription(media_id, title))); |
| 381 } |
| 382 } |
| 383 |
| 384 // Add timely sorted tab sources into vector. Most recent one first. |
| 385 tab_sources->clear(); |
| 386 for (auto it = tab_map.rbegin(); it != tab_map.rend(); ++it) { |
| 387 tab_sources->push_back(it->second); |
| 388 } |
297 } | 389 } |
298 | 390 |
299 void NativeDesktopMediaList::OnSourcesList( | 391 void NativeDesktopMediaList::OnSourcesList( |
300 const std::vector<SourceDescription>& new_sources) { | 392 const std::vector<SourceDescription>& new_sources) { |
301 typedef std::set<content::DesktopMediaID> SourceSet; | 393 typedef std::set<content::DesktopMediaID> SourceSet; |
302 SourceSet new_source_set; | 394 SourceSet new_source_set; |
303 for (size_t i = 0; i < new_sources.size(); ++i) { | 395 for (size_t i = 0; i < new_sources.size(); ++i) { |
304 new_source_set.insert(new_sources[i].id); | 396 new_source_set.insert(new_sources[i].id); |
305 } | 397 } |
306 // Iterate through the old sources to find the removed sources. | 398 // Iterate through the old sources to find the removed sources. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 } | 451 } |
360 | 452 |
361 void NativeDesktopMediaList::OnSourceThumbnail( | 453 void NativeDesktopMediaList::OnSourceThumbnail( |
362 int index, | 454 int index, |
363 const gfx::ImageSkia& image) { | 455 const gfx::ImageSkia& image) { |
364 DCHECK_LT(index, static_cast<int>(sources_.size())); | 456 DCHECK_LT(index, static_cast<int>(sources_.size())); |
365 sources_[index].thumbnail = image; | 457 sources_[index].thumbnail = image; |
366 observer_->OnSourceThumbnailChanged(index); | 458 observer_->OnSourceThumbnailChanged(index); |
367 } | 459 } |
368 | 460 |
| 461 void NativeDesktopMediaList::OnSourceTabThumbnail(SourceDescription source) { |
| 462 DCHECK(source.id.type == DesktopMediaID::TYPE_TAB); |
| 463 |
| 464 for (size_t i = 0; i < sources_.size(); ++i) { |
| 465 if (sources_[i].id == source.id) { |
| 466 // Use favicon as thumbnail for tab. |
| 467 std::pair<int, int> window_id(source.id.tab_id.render_process_id, |
| 468 source.id.tab_id.main_render_frame_id); |
| 469 if (tab_icon_map_.count(window_id)) { |
| 470 // Only do update when there is a change to avoid flickering. |
| 471 if (sources_[i].thumbnail.size() != tab_icon_map_[window_id].size() || |
| 472 sources_[i].name != source.name) { |
| 473 sources_[i].thumbnail = tab_icon_map_[window_id]; |
| 474 observer_->OnSourceThumbnailChanged(i); |
| 475 } |
| 476 } |
| 477 break; |
| 478 } |
| 479 } |
| 480 } |
| 481 |
369 void NativeDesktopMediaList::OnRefreshFinished() { | 482 void NativeDesktopMediaList::OnRefreshFinished() { |
370 BrowserThread::PostDelayedTask( | 483 BrowserThread::PostDelayedTask( |
371 BrowserThread::UI, FROM_HERE, | 484 BrowserThread::UI, FROM_HERE, |
372 base::Bind(&NativeDesktopMediaList::Refresh, | 485 base::Bind(&NativeDesktopMediaList::Refresh, |
373 weak_factory_.GetWeakPtr()), | 486 weak_factory_.GetWeakPtr()), |
374 update_period_); | 487 update_period_); |
375 } | 488 } |
OLD | NEW |