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

Side by Side Diff: chrome/browser/media/router/dial_media_sink_service.cc

Issue 2701633002: [Media Router] Add DialMediaSinkService and DeviceDescriptionService (Closed)
Patch Set: Add DialMediaSinkCacheService and unit test Created 3 years, 9 months 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media/router/dial_media_sink_service.h"
6
7 #include "chrome/browser/extensions/api/dial/device_description_fetcher.h"
8 #include "chrome/browser/extensions/api/dial/dial_api.h"
9 #include "chrome/browser/extensions/api/dial/dial_api_factory.h"
10 #include "chrome/browser/extensions/api/dial/dial_device_data.h"
11 #include "chrome/browser/media/router/media_sinks_observer.h"
12 #include "chrome/browser/media/router/mojo/media_router_mojo_impl.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "content/public/browser/browser_thread.h"
15
16 using base::Time;
17 using base::TimeDelta;
18 using content::BrowserThread;
19
20 namespace {
21 // The maximum time a response is expected after a M-SEARCH request.
22 const int kDialResponseTimeoutSecs = 2;
23 }
24
25 namespace media_router {
26
27 DialMediaSinkService::DialMediaSinkService(
28 const OnSinksDiscoveredCallback& callback,
29 content::BrowserContext* browser_context)
30 : MediaSinkService(callback),
31 dial_registry_(nullptr),
32 browser_context_(browser_context),
33 network_disconnected_(false) {
34 DCHECK_CURRENTLY_ON(BrowserThread::UI);
35 auto* profile = Profile::FromBrowserContext(browser_context_);
36 dial_api_ =
37 extensions::DialAPIFactory::GetInstance()->GetForBrowserContext(profile);
38 request_context_ = profile->GetRequestContext();
39
40 DCHECK(request_context_);
41 }
42
43 DialMediaSinkService::~DialMediaSinkService() {
44 if (!dial_registry_)
45 return;
46
47 content::BrowserThread::PostTask(
48 content::BrowserThread::IO, FROM_HERE,
49 base::Bind(&DialRegistry::UnregisterObserver,
50 base::Unretained(dial_registry_), this));
51 }
52
53 void DialMediaSinkService::Start() {
54 DCHECK_CURRENTLY_ON(BrowserThread::IO);
55 dial_registry()->RegisterObserver(this);
56 }
57
58 void DialMediaSinkService::AddSinkQuery(MediaSinksObserver* observer) {
59 NOTIMPLEMENTED();
60 }
61
62 void DialMediaSinkService::RemoveSinkQuery(MediaSinksObserver* observer) {
63 NOTIMPLEMENTED();
64 }
65
66 DialMediaSinkService::DialRegistry* DialMediaSinkService::dial_registry() {
67 DCHECK_CURRENTLY_ON(BrowserThread::IO);
68 DCHECK(dial_api_);
69
70 dial_registry_ = dial_api_->dial_registry();
71 return dial_registry_;
72 }
73
74 DeviceDescriptionService* DialMediaSinkService::description_service() {
75 DCHECK_CURRENTLY_ON(BrowserThread::IO);
76 if (!description_service_.get()) {
77 description_service_.reset(new DeviceDescriptionService(this));
78 }
79 return description_service_.get();
80 }
81
82 DialMediaSinkCacheService* DialMediaSinkService::cache_service() {
83 DCHECK_CURRENTLY_ON(BrowserThread::IO);
84 if (!cache_service_.get()) {
85 cache_service_.reset(new DialMediaSinkCacheService());
86 }
87 return cache_service_.get();
88 }
89
90 void DialMediaSinkService::OnDialDeviceEvent(
91 const DialRegistry::DeviceList& devices) {
92 DCHECK_CURRENTLY_ON(BrowserThread::IO);
93 DVLOG(2) << "DialMediaSinkService::OnDialDeviceEvent found " << devices.size()
94 << " devices";
95
96 std::set<std::string> device_labels;
97 for (const auto& device : devices)
98 device_labels.insert(device.label());
99
100 // Abort previous resolution. Always follow the latest device list.
101 for (const auto& pending_label : pending_device_labels_) {
102 if (device_labels.find(pending_label) == device_labels.end())
103 description_service()->MayStopDeviceDescriptionFetching(pending_label);
104 }
105
106 pending_device_labels_ = device_labels;
107
108 // Add a finish timer.
109 base::TimeDelta finish_delay =
110 TimeDelta::FromSeconds(kDialResponseTimeoutSecs) * devices.size();
111 finish_timer_.Start(FROM_HERE, finish_delay, this,
112 &DialMediaSinkService::FetchCompleted);
113
114 for (const auto& device : devices) {
115 DialDeviceDescription description;
116 if (description_service()->GetDeviceDescription(device, request_context_,
117 &description)) {
118 // Get device description from cache.
119 OnDeviceDescriptionAvailable(device.label(), description);
120 }
121 }
122 }
123
124 void DialMediaSinkService::OnDialError(DialRegistry::DialErrorCode type) {
125 DCHECK_CURRENTLY_ON(BrowserThread::IO);
126 DVLOG(2) << "OnDialError [DialErrorCode]: " << static_cast<int>(type);
127 }
128
129 void DialMediaSinkService::OnDeviceDescriptionAvailable(
130 const std::string& device_id,
131 const DialDeviceDescription& description) {
132 DCHECK_CURRENTLY_ON(BrowserThread::IO);
133 cache_service()->AddOrUpdateSink(description);
134 }
135
136 void DialMediaSinkService::OnDeviceDescriptionFetchError(
137 const std::string& device_label,
138 const std::string& error_message) {
139 DCHECK_CURRENTLY_ON(BrowserThread::IO);
140 DVLOG(2) << "OnDescriptionFetchesError [message]: " << error_message;
141 }
142
143 void DialMediaSinkService::FetchCompleted() {
144 DCHECK_CURRENTLY_ON(BrowserThread::IO);
145 DCHECK(!sink_discovery_callback_.is_null());
146
147 auto sinks = cache_service()->GetAliveSinks();
148 if (!IsDifferent(sinks, mrp_sinks_))
149 return;
150
151 sink_discovery_callback_.Run(sinks);
152 mrp_sinks_ = sinks;
153
154 cache_service()->PruneInactiveSinks(network_disconnected_,
155 description_service(), request_context_);
156 finish_timer_.Stop();
157 }
158
159 bool DialMediaSinkService::IsDifferent(
160 const std::vector<MediaSinkInternal> new_sinks,
161 const std::vector<MediaSinkInternal> old_sinks) {
162 std::map<std::string, const MediaSinkInternal*> old_sink_map;
163 for (auto& sink : old_sinks)
164 old_sink_map.insert(std::make_pair(sink.sink().id(), &sink));
165
166 std::vector<const MediaSinkInternal*> added;
167 std::vector<const MediaSinkInternal*> updated;
168
169 for (auto& sink : new_sinks) {
170 const auto& old_sink_it = old_sink_map.find(sink.sink().id());
171 // If |sink| does not exist in |old_sinks|.
172 if (old_sink_it == old_sink_map.end()) {
173 added.push_back(&sink);
174 } else {
175 if (sink != *(old_sink_it->second))
176 updated.push_back(&sink);
177
178 old_sink_map.erase(old_sink_it);
179 }
180 }
181
182 return !added.empty() || !old_sink_map.empty() || !updated.empty();
183 }
184
185 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698