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