Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2840)

Unified Diff: chrome/browser/media/ash_desktop_media_list.cc

Issue 100833002: Add AshDesktopMediaList and enable Desktop Capture API on Chrome OS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/media/ash_desktop_media_list.cc
diff --git a/chrome/browser/media/ash_desktop_media_list.cc b/chrome/browser/media/ash_desktop_media_list.cc
new file mode 100644
index 0000000000000000000000000000000000000000..166dd2f91315a5e7fbb6179a8e680e0f92801dfb
--- /dev/null
+++ b/chrome/browser/media/ash_desktop_media_list.cc
@@ -0,0 +1,214 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/ash_desktop_media_list.h"
+
+#include <map>
+
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "base/hash.h"
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/media/desktop_media_list_observer.h"
+#include "content/public/browser/browser_thread.h"
+#include "grit/generated_resources.h"
+#include "media/base/video_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/compositor/dip_util.h"
+#include "ui/gfx/image/image.h"
+#include "ui/snapshot/snapshot.h"
+
+using content::BrowserThread;
+using content::DesktopMediaID;
+
+namespace {
+
+// Update the list twice per second.
+const int kDefaultUpdatePeriod = 500;
+
+} // namespace
+
+AshDesktopMediaList::SourceDescription::SourceDescription(
+ DesktopMediaID id,
+ const base::string16& name)
+ : id(id),
+ name(name) {
+}
+
+AshDesktopMediaList::AshDesktopMediaList(int source_types)
+ : source_types_(source_types),
+ update_period_(base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)),
+ thumbnail_size_(100, 100),
+ view_dialog_id_(-1),
+ observer_(NULL),
+ pending_window_capture_requests_(0),
+ weak_factory_(this) {
+}
+
+AshDesktopMediaList::~AshDesktopMediaList() {}
+
+void AshDesktopMediaList::SetUpdatePeriod(base::TimeDelta period) {
+ DCHECK(!observer_);
+ update_period_ = period;
+}
+
+void AshDesktopMediaList::SetThumbnailSize(
+ const gfx::Size& thumbnail_size) {
+ thumbnail_size_ = thumbnail_size;
+}
+
+void AshDesktopMediaList::SetViewDialogWindowId(
+ content::DesktopMediaID::Id dialog_id) {
+ view_dialog_id_ = dialog_id;
+}
+
+void AshDesktopMediaList::StartUpdating(DesktopMediaListObserver* observer) {
+ DCHECK(!observer_);
+
+ observer_ = observer;
+ Refresh();
+}
+
+int AshDesktopMediaList::GetSourceCount() const {
+ return sources_.size();
+}
+
+const DesktopMediaList::Source& AshDesktopMediaList::GetSource(
+ int index) const {
+ return sources_[index];
+}
+
+// static
+bool AshDesktopMediaList::CompareSources(const SourceDescription& a,
+ const SourceDescription& b) {
+ return a.id < b.id;
+}
+
+void AshDesktopMediaList::Refresh() {
+ std::vector<SourceDescription> new_sources;
+ EnumerateSources(&new_sources);
+
+ // Sort the list of sources so that they appear in a predictable order.
+ std::sort(new_sources.begin(), new_sources.end(), CompareSources);
+
+ // Step through |new_sources| adding and removing entries from |sources_|, and
+ // notifying the |observer_|, until two match. Requires that |sources| and
+ // |sources_| have the same ordering.
+ size_t pos = 0;
+ while (pos < sources_.size() || pos < new_sources.size()) {
+ // If |sources_[pos]| is not in |new_sources| then remove it.
+ if (pos < sources_.size() &&
+ (pos == new_sources.size() || sources_[pos].id < new_sources[pos].id)) {
+ sources_.erase(sources_.begin() + pos);
+ observer_->OnSourceRemoved(pos);
+ continue;
+ }
+
+ if (pos == sources_.size() || !(sources_[pos].id == new_sources[pos].id)) {
+ sources_.insert(sources_.begin() + pos, Source());
+ sources_[pos].id = new_sources[pos].id;
+ sources_[pos].name = new_sources[pos].name;
+ observer_->OnSourceAdded(pos);
+ } else if (sources_[pos].name != new_sources[pos].name) {
+ sources_[pos].name = new_sources[pos].name;
+ observer_->OnSourceNameChanged(pos);
+ }
+
+ ++pos;
+ }
+
+ DCHECK_EQ(new_sources.size(), sources_.size());
+}
+
+void AshDesktopMediaList::EnumerateWindowsForRoot(
+ std::vector<AshDesktopMediaList::SourceDescription>* sources,
+ aura::Window* root_window,
+ int container_id) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ aura::Window* container = ash::Shell::GetContainer(root_window, container_id);
+ if (!container)
+ return;
+ for (aura::Window::Windows::const_iterator it = container->children().begin();
+ it != container->children().end(); ++it) {
+ if (!(*it)->IsVisible() || !(*it)->CanFocus())
+ continue;
+ content::DesktopMediaID id =
+ content::DesktopMediaID::RegisterAuraWindow(*it);
+ if (id.id == view_dialog_id_)
+ continue;
+ SourceDescription window_source(id, (*it)->title());
+ sources->push_back(window_source);
+
+ CaptureThumbnail(window_source.id, *it);
+ }
+}
+
+void AshDesktopMediaList::EnumerateSources(
+ std::vector<AshDesktopMediaList::SourceDescription>* sources) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
+
+ for (aura::Window::Windows::const_iterator iter = root_windows.begin();
+ iter != root_windows.end(); ++iter) {
+ if (source_types_ & SCREENS) {
+ SourceDescription screen_source(
+ content::DesktopMediaID::RegisterAuraWindow(*iter), (*iter)->title());
+ sources->push_back(screen_source);
+
+ CaptureThumbnail(screen_source.id, *iter);
+ }
+
+ if (source_types_ & WINDOWS) {
+ EnumerateWindowsForRoot(
+ sources, *iter, ash::internal::kShellWindowId_DefaultContainer);
+ EnumerateWindowsForRoot(
+ sources, *iter, ash::internal::kShellWindowId_AlwaysOnTopContainer);
+ EnumerateWindowsForRoot(
+ sources, *iter, ash::internal::kShellWindowId_DockedContainer);
+ }
+ }
+}
+
+void AshDesktopMediaList::CaptureThumbnail(content::DesktopMediaID id,
+ aura::Window* window) {
+ gfx::Rect window_rect(window->bounds().width(), window->bounds().height());
+ gfx::Rect scaled_rect = media::ComputeLetterboxRegion(
+ gfx::Rect(thumbnail_size_), window_rect.size());
+
+ ++pending_window_capture_requests_;
+ ui::GrapWindowSnapshotAsync(
+ window, window_rect,
+ scaled_rect.size(),
+ BrowserThread::GetBlockingPool(),
+ base::Bind(&AshDesktopMediaList::OnThumbnailCaptured,
+ weak_factory_.GetWeakPtr(),
+ id));
+}
+
+void AshDesktopMediaList::OnThumbnailCaptured(content::DesktopMediaID id,
+ const gfx::Image& image) {
+ for (size_t i = 0; i < sources_.size(); ++i) {
+ if (sources_[i].id == id) {
+ sources_[i].thumbnail = image.AsImageSkia();
+ observer_->OnSourceThumbnailChanged(i);
+ break;
+ }
+ }
+
+ --pending_window_capture_requests_;
+ DCHECK_GE(pending_window_capture_requests_, 0);
+
+ if (!pending_window_capture_requests_) {
+ // Once we've finished capturing all windows post a task for the next list
+ // update.
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&AshDesktopMediaList::Refresh,
+ weak_factory_.GetWeakPtr()),
+ update_period_);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698