Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/tab_desktop_media_list.h" | 5 #include "chrome/browser/media/tab_desktop_media_list.h" |
| 6 | 6 |
| 7 #include "base/hash.h" | 7 #include "base/hash.h" |
| 8 #include "base/threading/sequenced_worker_pool.h" | 8 #include "base/threading/sequenced_worker_pool.h" |
| 9 #include "chrome/browser/profiles/profile_manager.h" | 9 #include "chrome/browser/profiles/profile_manager.h" |
| 10 #include "chrome/browser/ui/browser.h" | 10 #include "chrome/browser/ui/browser.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 thumbnail_task_runner_ = | 66 thumbnail_task_runner_ = |
| 67 worker_pool->GetSequencedTaskRunner(worker_pool->GetSequenceToken()); | 67 worker_pool->GetSequencedTaskRunner(worker_pool->GetSequenceToken()); |
| 68 } | 68 } |
| 69 | 69 |
| 70 TabDesktopMediaList::~TabDesktopMediaList() {} | 70 TabDesktopMediaList::~TabDesktopMediaList() {} |
| 71 | 71 |
| 72 void TabDesktopMediaList::Refresh() { | 72 void TabDesktopMediaList::Refresh() { |
| 73 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 73 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 74 | 74 |
| 75 Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); | 75 Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); |
| 76 std::vector<Browser*> browsers; | 76 if (profile) { |
|
tommi (sloooow) - chröme
2016/08/17 11:38:00
nit: Change to an early return?
afakhry
2016/08/17 15:33:00
Do we need to execute the ScheduleNextRefresh at t
Sergey Ulanov
2016/08/18 05:42:26
If profile can change then the answer is yes. Mayb
afakhry
2016/08/18 16:36:51
It seems from the comment above the PostTaskAndRep
| |
| 77 for (auto* browser : *BrowserList::GetInstance()) { | 77 std::vector<Browser*> browsers; |
| 78 if (browser->profile()->GetOriginalProfile() == | 78 for (auto* browser : *BrowserList::GetInstance()) { |
| 79 profile->GetOriginalProfile()) { | 79 if (browser->profile()->GetOriginalProfile() == |
| 80 browsers.push_back(browser); | 80 profile->GetOriginalProfile()) { |
| 81 browsers.push_back(browser); | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 ImageHashesMap new_favicon_hashes; | |
| 86 std::vector<SourceDescription> sources; | |
| 87 std::map<base::TimeTicks, SourceDescription> tab_map; | |
| 88 std::vector<std::pair<DesktopMediaID, gfx::ImageSkia>> favicon_pairs; | |
| 89 | |
| 90 // Enumerate all tabs with their titles and favicons for a user profile. | |
| 91 for (auto* browser : browsers) { | |
| 92 const TabStripModel* tab_strip_model = browser->tab_strip_model(); | |
| 93 DCHECK(tab_strip_model); | |
| 94 | |
| 95 for (int i = 0; i < tab_strip_model->count(); i++) { | |
| 96 // Create id for tab. | |
| 97 content::WebContents* contents = tab_strip_model->GetWebContentsAt(i); | |
| 98 DCHECK(contents); | |
| 99 content::RenderFrameHost* main_frame = contents->GetMainFrame(); | |
| 100 DCHECK(main_frame); | |
| 101 DesktopMediaID media_id( | |
| 102 DesktopMediaID::TYPE_WEB_CONTENTS, DesktopMediaID::kNullId, | |
| 103 content::WebContentsMediaCaptureId( | |
| 104 main_frame->GetProcess()->GetID(), main_frame->GetRoutingID())); | |
| 105 | |
| 106 // Get tab's last active time stamp. | |
| 107 const base::TimeTicks t = contents->GetLastActiveTime(); | |
| 108 tab_map.insert(std::make_pair( | |
| 109 t, SourceDescription(media_id, contents->GetTitle()))); | |
| 110 | |
| 111 // Get favicon for tab. | |
| 112 favicon::FaviconDriver* favicon_driver = | |
| 113 favicon::ContentFaviconDriver::FromWebContents(contents); | |
| 114 if (!favicon_driver) | |
| 115 continue; | |
| 116 | |
| 117 gfx::Image favicon = favicon_driver->GetFavicon(); | |
| 118 if (favicon.IsEmpty()) | |
| 119 continue; | |
| 120 | |
| 121 // Only new or changed favicon need update. | |
| 122 new_favicon_hashes[media_id] = GetImageHash(favicon); | |
| 123 if (!favicon_hashes_.count(media_id) || | |
| 124 (favicon_hashes_[media_id] != new_favicon_hashes[media_id])) { | |
| 125 gfx::ImageSkia image = favicon.AsImageSkia(); | |
| 126 image.MakeThreadSafe(); | |
| 127 favicon_pairs.push_back(std::make_pair(media_id, image)); | |
| 128 } | |
| 129 } | |
| 130 } | |
| 131 favicon_hashes_ = new_favicon_hashes; | |
| 132 | |
| 133 // Sort tab sources by time. Most recent one first. Then update sources | |
| 134 // list. | |
| 135 for (auto it = tab_map.rbegin(); it != tab_map.rend(); ++it) { | |
| 136 sources.push_back(it->second); | |
| 137 } | |
| 138 UpdateSourcesList(sources); | |
| 139 | |
| 140 for (const auto& it : favicon_pairs) { | |
| 141 // Create a thumbail in a different thread and update the thumbnail in | |
| 142 // current thread. | |
| 143 base::PostTaskAndReplyWithResult( | |
| 144 thumbnail_task_runner_.get(), FROM_HERE, | |
| 145 base::Bind(&CreateEnclosedFaviconImage, thumbnail_size_, it.second), | |
| 146 base::Bind(&TabDesktopMediaList::UpdateSourceThumbnail, | |
| 147 weak_factory_.GetWeakPtr(), it.first)); | |
| 81 } | 148 } |
| 82 } | 149 } |
| 83 | |
| 84 ImageHashesMap new_favicon_hashes; | |
| 85 std::vector<SourceDescription> sources; | |
| 86 std::map<base::TimeTicks, SourceDescription> tab_map; | |
| 87 std::vector<std::pair<DesktopMediaID, gfx::ImageSkia>> favicon_pairs; | |
| 88 | |
| 89 // Enumerate all tabs with their titles and favicons for a user profile. | |
| 90 for (auto* browser : browsers) { | |
| 91 const TabStripModel* tab_strip_model = browser->tab_strip_model(); | |
| 92 DCHECK(tab_strip_model); | |
| 93 | |
| 94 for (int i = 0; i < tab_strip_model->count(); i++) { | |
| 95 // Create id for tab. | |
| 96 content::WebContents* contents = tab_strip_model->GetWebContentsAt(i); | |
| 97 DCHECK(contents); | |
| 98 content::RenderFrameHost* main_frame = contents->GetMainFrame(); | |
| 99 DCHECK(main_frame); | |
| 100 DesktopMediaID media_id( | |
| 101 DesktopMediaID::TYPE_WEB_CONTENTS, DesktopMediaID::kNullId, | |
| 102 content::WebContentsMediaCaptureId(main_frame->GetProcess()->GetID(), | |
| 103 main_frame->GetRoutingID())); | |
| 104 | |
| 105 // Get tab's last active time stamp. | |
| 106 const base::TimeTicks t = contents->GetLastActiveTime(); | |
| 107 tab_map.insert( | |
| 108 std::make_pair(t, SourceDescription(media_id, contents->GetTitle()))); | |
| 109 | |
| 110 // Get favicon for tab. | |
| 111 favicon::FaviconDriver* favicon_driver = | |
| 112 favicon::ContentFaviconDriver::FromWebContents(contents); | |
| 113 if (!favicon_driver) | |
| 114 continue; | |
| 115 | |
| 116 gfx::Image favicon = favicon_driver->GetFavicon(); | |
| 117 if (favicon.IsEmpty()) | |
| 118 continue; | |
| 119 | |
| 120 // Only new or changed favicon need update. | |
| 121 new_favicon_hashes[media_id] = GetImageHash(favicon); | |
| 122 if (!favicon_hashes_.count(media_id) || | |
| 123 (favicon_hashes_[media_id] != new_favicon_hashes[media_id])) { | |
| 124 gfx::ImageSkia image = favicon.AsImageSkia(); | |
| 125 image.MakeThreadSafe(); | |
| 126 favicon_pairs.push_back(std::make_pair(media_id, image)); | |
| 127 } | |
| 128 } | |
| 129 } | |
| 130 favicon_hashes_ = new_favicon_hashes; | |
| 131 | |
| 132 // Sort tab sources by time. Most recent one first. Then update sources list. | |
| 133 for (auto it = tab_map.rbegin(); it != tab_map.rend(); ++it) { | |
| 134 sources.push_back(it->second); | |
| 135 } | |
| 136 UpdateSourcesList(sources); | |
| 137 | |
| 138 for (const auto& it : favicon_pairs) { | |
| 139 // Create a thumbail in a different thread and update the thumbnail in | |
| 140 // current thread. | |
| 141 base::PostTaskAndReplyWithResult( | |
| 142 thumbnail_task_runner_.get(), FROM_HERE, | |
| 143 base::Bind(&CreateEnclosedFaviconImage, thumbnail_size_, it.second), | |
| 144 base::Bind(&TabDesktopMediaList::UpdateSourceThumbnail, | |
| 145 weak_factory_.GetWeakPtr(), it.first)); | |
| 146 } | |
| 147 | |
| 148 // ScheduleNextRefresh() needs to be called after all calls for | 150 // ScheduleNextRefresh() needs to be called after all calls for |
| 149 // UpdateSourceThumbnail() have done. Therefore, a DoNothing task is posted | 151 // UpdateSourceThumbnail() have done. Therefore, a DoNothing task is posted |
| 150 // to the same sequenced task runner that CreateEnlargedFaviconImag() | 152 // to the same sequenced task runner that CreateEnlargedFaviconImag() |
| 151 // is posted. | 153 // is posted. |
| 152 thumbnail_task_runner_.get()->PostTaskAndReply( | 154 thumbnail_task_runner_.get()->PostTaskAndReply( |
| 153 FROM_HERE, base::Bind(&base::DoNothing), | 155 FROM_HERE, base::Bind(&base::DoNothing), |
| 154 base::Bind(&TabDesktopMediaList::ScheduleNextRefresh, | 156 base::Bind(&TabDesktopMediaList::ScheduleNextRefresh, |
| 155 weak_factory_.GetWeakPtr())); | 157 weak_factory_.GetWeakPtr())); |
| 156 } | 158 } |
| OLD | NEW |