forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcast_session_id_map.cc
132 lines (112 loc) · 4.69 KB
/
cast_session_id_map.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2018 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 "chromecast/browser/cast_session_id_map.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "base/time/time.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
namespace chromecast {
namespace shell {
// A small class that listens for the destruction of a WebContents, and forwards
// the event to the CastSessionIdMap with the appropriate group_id.
class CastSessionIdMap::GroupObserver : content::WebContentsObserver {
public:
using GroupDestroyedCallback =
base::OnceCallback<void(base::UnguessableToken)>;
GroupObserver(content::WebContents* web_contents,
GroupDestroyedCallback destroyed_callback)
: destroyed_callback_(std::move(destroyed_callback)),
group_id_(web_contents->GetAudioGroupId()) {
content::WebContentsObserver::Observe(web_contents);
}
private:
// content::WebContentsObserver implementation:
void WebContentsDestroyed() override {
DCHECK(destroyed_callback_);
content::WebContentsObserver::Observe(nullptr);
std::move(destroyed_callback_).Run(group_id_);
}
GroupDestroyedCallback destroyed_callback_;
base::UnguessableToken group_id_;
};
// static
CastSessionIdMap* CastSessionIdMap::GetInstance(
base::SequencedTaskRunner* task_runner) {
static base::NoDestructor<CastSessionIdMap> map(task_runner);
return map.get();
}
// static
void CastSessionIdMap::SetSessionId(std::string session_id,
content::WebContents* web_contents) {
base::UnguessableToken group_id = web_contents->GetAudioGroupId();
// Unretained is safe here, because the singleton CastSessionIdMap never gets
// destroyed.
auto destroyed_callback = base::BindOnce(&CastSessionIdMap::OnGroupDestroyed,
base::Unretained(GetInstance()));
auto group_observer = std::make_unique<GroupObserver>(
web_contents, std::move(destroyed_callback));
GetInstance()->SetSessionIdInternal(session_id, group_id,
std::move(group_observer));
}
// static
std::string CastSessionIdMap::GetSessionId(const std::string& group_id) {
return GetInstance()->GetSessionIdInternal(group_id);
}
CastSessionIdMap::CastSessionIdMap(base::SequencedTaskRunner* task_runner)
: task_runner_(task_runner) {
DCHECK(task_runner_);
DETACH_FROM_SEQUENCE(sequence_checker_);
}
CastSessionIdMap::~CastSessionIdMap() = default;
void CastSessionIdMap::SetSessionIdInternal(
std::string session_id,
base::UnguessableToken group_id,
std::unique_ptr<GroupObserver> group_observer) {
if (!task_runner_->RunsTasksInCurrentSequence()) {
// Unretained is safe here, because the singleton CastSessionIdMap never
// gets destroyed.
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&CastSessionIdMap::SetSessionIdInternal,
base::Unretained(this), std::move(session_id),
group_id, std::move(group_observer)));
return;
}
// This check is required to bind to the current sequence.
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(GetSessionIdInternal(group_id.ToString()).empty());
DCHECK(group_observer);
DVLOG(1) << "Mapping session_id=" << session_id
<< " to group_id=" << group_id.ToString();
auto group_data = std::make_pair(session_id, std::move(group_observer));
mapping_.emplace(group_id.ToString(), std::move(group_data));
}
std::string CastSessionIdMap::GetSessionIdInternal(
const std::string& group_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = mapping_.find(group_id);
if (it != mapping_.end())
return it->second.first;
return std::string();
}
void CastSessionIdMap::OnGroupDestroyed(base::UnguessableToken group_id) {
// Unretained is safe here, because the singleton CastSessionIdMap never gets
// destroyed.
task_runner_->PostTask(FROM_HERE,
base::BindOnce(&CastSessionIdMap::RemoveGroupId,
base::Unretained(this), group_id));
}
void CastSessionIdMap::RemoveGroupId(base::UnguessableToken group_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = mapping_.find(group_id.ToString());
if (it != mapping_.end()) {
DVLOG(1) << "Removing mapping for session_id=" << it->second.first
<< " to group_id=" << group_id.ToString();
mapping_.erase(it);
}
}
} // namespace shell
} // namespace chromecast