blob: 8a20598af67f82db03a1dffad8601597df05d1c3 [file] [log] [blame]
// 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 "content/public/browser/desktop_media_id.h"
#include <stdint.h>
#include <vector>
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#if defined(USE_AURA)
#include "ui/aura/window.h" // nogncheck
#include "ui/aura/window_observer.h" // nogncheck
#endif // defined(USE_AURA)
namespace {
#if defined(USE_AURA)
class AuraWindowRegistry : public aura::WindowObserver {
public:
static AuraWindowRegistry* GetInstance() {
return base::Singleton<AuraWindowRegistry>::get();
}
int RegisterWindow(aura::Window* window) {
IDMap<aura::Window>::const_iterator it(&registered_windows_);
for (; !it.IsAtEnd(); it.Advance()) {
if (it.GetCurrentValue() == window)
return it.GetCurrentKey();
}
window->AddObserver(this);
return registered_windows_.Add(window);
}
aura::Window* GetWindowById(int id) {
return registered_windows_.Lookup(id);
}
private:
friend struct base::DefaultSingletonTraits<AuraWindowRegistry>;
AuraWindowRegistry() {}
~AuraWindowRegistry() override {}
// WindowObserver overrides.
void OnWindowDestroying(aura::Window* window) override {
IDMap<aura::Window>::iterator it(&registered_windows_);
for (; !it.IsAtEnd(); it.Advance()) {
if (it.GetCurrentValue() == window) {
registered_windows_.Remove(it.GetCurrentKey());
return;
}
}
NOTREACHED();
}
IDMap<aura::Window> registered_windows_;
DISALLOW_COPY_AND_ASSIGN(AuraWindowRegistry);
};
#endif // defined(USE_AURA)
} // namespace
namespace content {
const char kScreenPrefix[] = "screen";
const char kWindowPrefix[] = "window";
#if defined(USE_AURA)
// static
DesktopMediaID DesktopMediaID::RegisterAuraWindow(DesktopMediaID::Type type,
aura::Window* window) {
DCHECK(type == TYPE_SCREEN || type == TYPE_WINDOW);
DCHECK(window);
DesktopMediaID media_id(type, kNullId);
media_id.aura_id = AuraWindowRegistry::GetInstance()->RegisterWindow(window);
return media_id;
}
// static
aura::Window* DesktopMediaID::GetAuraWindowById(const DesktopMediaID& id) {
return AuraWindowRegistry::GetInstance()->GetWindowById(id.aura_id);
}
#endif // defined(USE_AURA)
bool DesktopMediaID::operator<(const DesktopMediaID& other) const {
#if defined(USE_AURA)
return std::tie(type, id, aura_id, web_contents_id, audio_share) <
std::tie(other.type, other.id, other.aura_id, other.web_contents_id,
other.audio_share);
#else
return std::tie(type, id, web_contents_id, audio_share) <
std::tie(other.type, other.id, other.web_contents_id,
other.audio_share);
#endif
}
bool DesktopMediaID::operator==(const DesktopMediaID& other) const {
#if defined(USE_AURA)
return type == other.type && id == other.id && aura_id == other.aura_id &&
web_contents_id == other.web_contents_id &&
audio_share == other.audio_share;
#else
return type == other.type && id == other.id &&
web_contents_id == other.web_contents_id &&
audio_share == other.audio_share;
#endif
}
// static
// Input string should in format:
// for WebContents:
// web-contents-media-stream://"render_process_id":"render_process_id"
// for no aura screen and window: screen:"window_id" or window:"window_id"
// for aura screen and window: screen:"window_id:aura_id" or
// window:"window_id:aura_id".
DesktopMediaID DesktopMediaID::Parse(const std::string& str) {
// For WebContents type.
WebContentsMediaCaptureId web_id = WebContentsMediaCaptureId::Parse(str);
if (!web_id.is_null())
return DesktopMediaID(TYPE_WEB_CONTENTS, 0, web_id);
// For screen and window types.
std::vector<std::string> parts = base::SplitString(
str, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
#if defined(USE_AURA)
if (parts.size() != 3)
return DesktopMediaID();
#else
if (parts.size() != 2)
return DesktopMediaID();
#endif
Type type = TYPE_NONE;
if (parts[0] == kScreenPrefix) {
type = TYPE_SCREEN;
} else if (parts[0] == kWindowPrefix) {
type = TYPE_WINDOW;
} else {
return DesktopMediaID();
}
int64_t id;
if (!base::StringToInt64(parts[1], &id))
return DesktopMediaID();
DesktopMediaID media_id(type, id);
#if defined(USE_AURA)
int64_t aura_id;
if (!base::StringToInt64(parts[2], &aura_id))
return DesktopMediaID();
media_id.aura_id = aura_id;
#endif // defined(USE_AURA)
return media_id;
}
std::string DesktopMediaID::ToString() const {
std::string prefix;
switch (type) {
case TYPE_NONE:
NOTREACHED();
return std::string();
case TYPE_SCREEN:
prefix = kScreenPrefix;
break;
case TYPE_WINDOW:
prefix = kWindowPrefix;
break;
case TYPE_WEB_CONTENTS:
return web_contents_id.ToString();
break;
}
DCHECK(!prefix.empty());
// Screen and Window types.
prefix.append(":");
prefix.append(base::Int64ToString(id));
#if defined(USE_AURA)
prefix.append(":");
prefix.append(base::Int64ToString(aura_id));
#endif // defined(USE_AURA)
return prefix;
}
} // namespace content