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