Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 "extensions/browser/api/media_perception_private/media_perception_api_m anager.h" | |
| 6 | |
| 7 #include "base/lazy_instance.h" | |
| 8 #include "base/memory/ptr_util.h" | |
| 9 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 10 #include "chromeos/dbus/media_analytics_client.h" | |
| 11 #include "chromeos/dbus/upstart_client.h" | |
| 12 #include "extensions/browser/event_router.h" | |
| 13 #include "extensions/browser/extension_function.h" | |
| 14 | |
| 15 namespace media_perception = extensions::api::media_perception_private; | |
| 16 | |
| 17 namespace extensions { | |
| 18 | |
| 19 namespace { | |
| 20 | |
| 21 // p_result is owned by the caller. | |
| 22 void PointProtoToIdl(const mri::Point& point, | |
|
tbarzic
2017/05/09 01:28:36
make this return unique_ptr<media_perception::Poin
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 23 media_perception::Point* p_result) { | |
| 24 if (point.has_x()) { | |
| 25 p_result->x.reset(new double(point.x())); | |
| 26 } | |
| 27 if (point.has_y()) { | |
| 28 p_result->y.reset(new double(point.y())); | |
| 29 } | |
| 30 } | |
| 31 | |
| 32 // bbox_result is owned by the caller. | |
| 33 void BoundingBoxProtoToIdl(const mri::BoundingBox& bounding_box, | |
| 34 media_perception::BoundingBox* bbox_result) { | |
| 35 if (bounding_box.has_normalized()) { | |
| 36 bbox_result->normalized.reset(new bool(bounding_box.normalized())); | |
| 37 } | |
| 38 if (bounding_box.has_top_left()) { | |
| 39 bbox_result->top_left.reset(new media_perception::Point()); | |
| 40 PointProtoToIdl(bounding_box.top_left(), bbox_result->top_left.get()); | |
| 41 } | |
| 42 if (bounding_box.has_bottom_right()) { | |
| 43 bbox_result->bottom_right.reset(new media_perception::Point()); | |
| 44 PointProtoToIdl(bounding_box.bottom_right(), | |
| 45 bbox_result->bottom_right.get()); | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 media_perception::Entity EntityProtoToIdl(const mri::Entity& entity) { | |
| 50 media_perception::Entity e_result; | |
| 51 if (entity.has_id()) { | |
| 52 e_result.id.reset(new int(entity.id())); | |
| 53 } | |
| 54 if (entity.has_type()) { | |
| 55 switch (entity.type()) { | |
|
tbarzic
2017/05/09 01:28:36
consider moving this to a helper method
ConvertEnt
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 56 case mri::Entity::FACE: | |
| 57 e_result.type = media_perception::ENTITY_TYPE_FACE; | |
| 58 break; | |
| 59 case mri::Entity::PERSON: | |
| 60 e_result.type = media_perception::ENTITY_TYPE_PERSON; | |
| 61 break; | |
| 62 default: | |
|
tbarzic
2017/05/09 01:28:36
case mri::Entity::UNSPECIFIED:
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 63 e_result.type = media_perception::ENTITY_TYPE_UNSPECIFIED; | |
| 64 } | |
| 65 } | |
| 66 if (entity.has_confidence()) { | |
| 67 e_result.confidence.reset(new double(entity.confidence())); | |
| 68 } | |
| 69 if (entity.has_bounding_box()) { | |
| 70 e_result.bounding_box.reset(new media_perception::BoundingBox()); | |
| 71 BoundingBoxProtoToIdl(entity.bounding_box(), e_result.bounding_box.get()); | |
|
tbarzic
2017/05/09 01:28:36
e_result.bounding_box = BoundingBoxProtoToIdl(enti
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 72 } | |
| 73 return e_result; | |
| 74 } | |
| 75 | |
| 76 media_perception::FramePerception FramePerceptionProtoToIdl( | |
| 77 const mri::FramePerception& frame_perception) { | |
| 78 media_perception::FramePerception fp_result; | |
| 79 if (frame_perception.has_frame_id()) { | |
| 80 fp_result.frame_id.reset(new int(frame_perception.frame_id())); | |
| 81 } | |
| 82 if (frame_perception.has_frame_width_in_px()) { | |
| 83 fp_result.frame_width_in_px.reset( | |
| 84 new int(frame_perception.frame_width_in_px())); | |
| 85 } | |
| 86 if (frame_perception.has_frame_height_in_px()) { | |
| 87 fp_result.frame_height_in_px.reset( | |
| 88 new int(frame_perception.frame_height_in_px())); | |
| 89 } | |
| 90 if (frame_perception.has_timestamp()) { | |
| 91 fp_result.timestamp.reset(new double(frame_perception.timestamp())); | |
| 92 } | |
| 93 if (frame_perception.entity_size() > 0) { | |
| 94 fp_result.entities.reset(new std::vector<media_perception::Entity>()); | |
| 95 for (const auto& entity : frame_perception.entity()) { | |
| 96 fp_result.entities->emplace_back(EntityProtoToIdl(entity)); | |
| 97 } | |
| 98 } | |
| 99 return fp_result; | |
| 100 } | |
| 101 | |
| 102 media_perception::PerceptionSample PerceptionSampleProtoToIdl( | |
| 103 const mri::PerceptionSample& perception_sample) { | |
| 104 media_perception::PerceptionSample ps_result; | |
| 105 if (perception_sample.has_frame_perception()) { | |
| 106 ps_result.frame_perception.reset(new media_perception::FramePerception( | |
| 107 FramePerceptionProtoToIdl(perception_sample.frame_perception()))); | |
| 108 } | |
| 109 // TODO(lasoren): Implement ImageFrameProtoToIdl. | |
| 110 return ps_result; | |
| 111 } | |
| 112 | |
| 113 } // namespace | |
| 114 | |
| 115 media_perception::State StateProtoToIdl(const mri::State& state) { | |
| 116 media_perception::State s_result; | |
| 117 if (state.has_status()) { | |
| 118 switch (state.status()) { | |
| 119 case mri::State::UNINITIALIZED: | |
| 120 s_result.status = media_perception::STATUS_UNINITIALIZED; | |
| 121 break; | |
| 122 case mri::State::STARTED: | |
| 123 s_result.status = media_perception::STATUS_STARTED; | |
| 124 break; | |
| 125 case mri::State::RUNNING: | |
| 126 s_result.status = media_perception::STATUS_RUNNING; | |
| 127 break; | |
| 128 case mri::State::SUSPENDED: | |
| 129 s_result.status = media_perception::STATUS_SUSPENDED; | |
| 130 break; | |
| 131 default: | |
| 132 // Status unset. | |
| 133 break; | |
| 134 } | |
| 135 } | |
| 136 if (state.has_device_context()) { | |
| 137 s_result.device_context.reset(new std::string(state.device_context())); | |
| 138 } | |
| 139 return s_result; | |
| 140 } | |
| 141 | |
| 142 mri::State StateIdlToProto(const media_perception::State& state) { | |
| 143 mri::State s_result; | |
| 144 switch (state.status) { | |
| 145 case media_perception::STATUS_UNINITIALIZED: | |
| 146 s_result.set_status(mri::State::UNINITIALIZED); | |
| 147 break; | |
| 148 case media_perception::STATUS_STARTED: | |
| 149 s_result.set_status(mri::State::STARTED); | |
| 150 break; | |
| 151 case media_perception::STATUS_RUNNING: | |
| 152 s_result.set_status(mri::State::RUNNING); | |
| 153 break; | |
| 154 case media_perception::STATUS_SUSPENDED: | |
| 155 s_result.set_status(mri::State::SUSPENDED); | |
| 156 break; | |
| 157 default: | |
| 158 // Status unset. | |
|
tbarzic
2017/05/09 01:28:36
NOTREACHED() << "Status not set."
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 159 break; | |
| 160 } | |
| 161 if (state.device_context) { | |
| 162 s_result.set_device_context(*state.device_context); | |
| 163 } | |
| 164 return s_result; | |
| 165 } | |
| 166 | |
| 167 media_perception::MediaPerception MediaPerceptionProtoToIdl( | |
| 168 const mri::MediaPerception& media_perception) { | |
| 169 media_perception::MediaPerception mp_result; | |
| 170 if (media_perception.has_timestamp()) { | |
| 171 mp_result.timestamp.reset(new double(media_perception.timestamp())); | |
| 172 } | |
| 173 if (media_perception.frame_perception_size() > 0) { | |
| 174 mp_result.frame_perceptions.reset( | |
| 175 new std::vector<media_perception::FramePerception>()); | |
| 176 for (const auto& frame_perception : media_perception.frame_perception()) { | |
| 177 mp_result.frame_perceptions->emplace_back( | |
| 178 FramePerceptionProtoToIdl(frame_perception)); | |
| 179 } | |
| 180 } | |
| 181 return mp_result; | |
| 182 } | |
| 183 | |
| 184 media_perception::Diagnostics DiagnosticsProtoToIdl( | |
| 185 const mri::Diagnostics& diagnostics) { | |
| 186 media_perception::Diagnostics d_result; | |
| 187 if (diagnostics.perception_sample_size() > 0) { | |
| 188 d_result.perception_samples.reset( | |
| 189 new std::vector<media_perception::PerceptionSample>()); | |
| 190 for (const auto& perception_sample : diagnostics.perception_sample()) { | |
| 191 d_result.perception_samples->emplace_back( | |
| 192 PerceptionSampleProtoToIdl(perception_sample)); | |
| 193 } | |
| 194 } | |
| 195 return d_result; | |
| 196 } | |
| 197 | |
| 198 // static | |
| 199 MediaPerceptionAPIManager* MediaPerceptionAPIManager::Get( | |
| 200 content::BrowserContext* context) { | |
| 201 return GetFactoryInstance()->Get(context); | |
| 202 } | |
| 203 | |
| 204 static base::LazyInstance< | |
| 205 BrowserContextKeyedAPIFactory<MediaPerceptionAPIManager>>::DestructorAtExit | |
| 206 g_factory = LAZY_INSTANCE_INITIALIZER; | |
|
tbarzic
2017/05/09 01:28:36
I think this should be leaky
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 207 | |
| 208 // static | |
| 209 BrowserContextKeyedAPIFactory<MediaPerceptionAPIManager>* | |
| 210 MediaPerceptionAPIManager::GetFactoryInstance() { | |
| 211 return g_factory.Pointer(); | |
| 212 } | |
| 213 | |
| 214 MediaPerceptionAPIManager::MediaPerceptionAPIManager( | |
| 215 content::BrowserContext* context) | |
| 216 : browser_context_(context), analytics_process_running_(false) { | |
| 217 chromeos::MediaAnalyticsClient* dbus_client = | |
| 218 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
| 219 dbus_client->SetMediaPerceptionSignalHandler( | |
| 220 base::Bind(&MediaPerceptionAPIManager::MediaPerceptionSignalHandler, | |
| 221 base::Unretained(this))); | |
| 222 } | |
| 223 | |
| 224 MediaPerceptionAPIManager::~MediaPerceptionAPIManager() { | |
| 225 chromeos::MediaAnalyticsClient* dbus_client = | |
| 226 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
| 227 dbus_client->UnsetMediaPerceptionSignalHandler(); | |
| 228 // TODO(lasoren): Verify this gets called at the right time. | |
|
tbarzic
2017/05/09 01:28:36
What do you mean by this?
Luke Sorenson
2017/05/09 21:05:44
I was curious when the destructor for this class i
| |
| 229 // Stop the separate media analytics process. | |
| 230 chromeos::UpstartClient* upstart_client = | |
| 231 chromeos::DBusThreadManager::Get()->GetUpstartClient(); | |
| 232 upstart_client->StopMediaAnalytics(); | |
| 233 } | |
| 234 | |
| 235 void MediaPerceptionAPIManager::GetState(const APIStateCallback& callback) { | |
| 236 // Return uninitialized state if the media analytics process isn't running. | |
| 237 if (!analytics_process_running_) { | |
| 238 media_perception::State state_unitialized; | |
| 239 state_unitialized.status = media_perception::STATUS_UNINITIALIZED; | |
| 240 callback.Run(true, std::move(state_unitialized)); | |
| 241 return; | |
| 242 } | |
| 243 chromeos::MediaAnalyticsClient* dbus_client = | |
| 244 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
| 245 dbus_client->State(mri::State(), // Passing empty state changes nothing. | |
| 246 base::Bind(&MediaPerceptionAPIManager::StateCallback, | |
| 247 base::Unretained(this), callback)); | |
| 248 } | |
| 249 | |
| 250 void MediaPerceptionAPIManager::SetState(const media_perception::State& state, | |
| 251 const APIStateCallback& callback) { | |
| 252 mri::State state_proto = StateIdlToProto(state); | |
| 253 if (state_proto.status() != mri::State::RUNNING && | |
|
tbarzic
2017/05/09 01:28:36
This can probably be a DCHECK.
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 254 state_proto.status() != mri::State::SUSPENDED) { | |
| 255 LOG(ERROR) << "Cannot set state to something other than RUNNING or " | |
| 256 "SUSPENDED."; | |
| 257 media_perception::State empty_state; | |
| 258 callback.Run(false, std::move(empty_state)); | |
| 259 return; | |
| 260 } | |
| 261 if (!analytics_process_running_) { | |
|
tbarzic
2017/05/09 01:28:36
will we ever need to stop the process (from the ap
Luke Sorenson
2017/05/09 21:05:45
From a simplicity and security standpoint, we didn
| |
| 262 if (state_proto.status() == mri::State::RUNNING) { | |
| 263 chromeos::UpstartClient* dbus_client = | |
| 264 chromeos::DBusThreadManager::Get()->GetUpstartClient(); | |
| 265 dbus_client->StartMediaAnalytics( | |
| 266 base::Bind(&MediaPerceptionAPIManager::UpstartCallback, | |
| 267 base::Unretained(this), callback, state_proto)); | |
|
tbarzic
2017/05/09 01:28:37
Use weak ptr here (and elsewhere where you call in
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 268 } else { | |
| 269 media_perception::State empty_state; | |
| 270 callback.Run(false, std::move(empty_state)); | |
| 271 } | |
| 272 } else { | |
| 273 SetStateInternal(callback, state_proto); | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 void MediaPerceptionAPIManager::SetStateInternal( | |
| 278 const APIStateCallback& callback, | |
| 279 const mri::State& state) { | |
| 280 chromeos::MediaAnalyticsClient* dbus_client = | |
| 281 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
| 282 dbus_client->State(state, | |
| 283 base::Bind(&MediaPerceptionAPIManager::StateCallback, | |
| 284 base::Unretained(this), callback)); | |
| 285 } | |
| 286 | |
| 287 void MediaPerceptionAPIManager::GetDiagnostics( | |
| 288 const APIGetDiagnosticsCallback& callback) { | |
| 289 chromeos::MediaAnalyticsClient* dbus_client = | |
| 290 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
| 291 dbus_client->GetDiagnostics( | |
| 292 base::Bind(&MediaPerceptionAPIManager::GetDiagnosticsCallback, | |
| 293 base::Unretained(this), callback)); | |
| 294 } | |
| 295 | |
| 296 void MediaPerceptionAPIManager::UpstartCallback( | |
| 297 const APIStateCallback& callback, | |
| 298 const mri::State& state, | |
| 299 bool succeeded) { | |
|
tbarzic
2017/05/09 01:28:36
if (!success) {
callback.Run(false, media_percep
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 300 if (succeeded) { | |
| 301 analytics_process_running_ = true; | |
| 302 SetStateInternal(callback, state); | |
| 303 } else { | |
| 304 analytics_process_running_ = false; | |
| 305 LOG(ERROR) << "Failed to start media analytics process via Upstart."; | |
| 306 media_perception::State empty_state; | |
| 307 callback.Run(false, std::move(empty_state)); | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 void MediaPerceptionAPIManager::StateCallback(const APIStateCallback& callback, | |
| 312 bool succeeded, | |
| 313 const mri::State& state_proto) { | |
| 314 media_perception::State state; | |
| 315 if (!succeeded) { | |
| 316 state.status = media_perception::STATUS_TIMEOUT; | |
| 317 callback.Run(false, std::move(state)); | |
|
tbarzic
2017/05/09 01:28:36
just:
callback.Run(false, media_perception::State)
Luke Sorenson
2017/05/09 21:05:44
Is there any precedent for / is it possible to res
tbarzic
2017/05/09 21:19:14
yes you can.
My preferred approach would be for th
Luke Sorenson
2017/05/10 18:50:16
Acknowledged.
| |
| 318 return; | |
| 319 } | |
| 320 state = StateProtoToIdl(state_proto); | |
| 321 callback.Run(true, std::move(state)); | |
|
tbarzic
2017/05/09 01:28:36
callback.Run(true, StateProtoToIdl(state_proto));
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 322 } | |
| 323 | |
| 324 void MediaPerceptionAPIManager::GetDiagnosticsCallback( | |
| 325 const APIGetDiagnosticsCallback& callback, | |
| 326 bool succeeded, | |
| 327 const mri::Diagnostics& diagnostics_proto) { | |
| 328 media_perception::Diagnostics diagnostics; | |
| 329 if (!succeeded) { | |
| 330 callback.Run(false, std::move(diagnostics)); | |
| 331 return; | |
|
tbarzic
2017/05/09 01:28:36
same as for StateCallback applies
Luke Sorenson
2017/05/09 21:05:44
Done.
| |
| 332 } | |
| 333 diagnostics = DiagnosticsProtoToIdl(diagnostics_proto); | |
| 334 callback.Run(true, std::move(diagnostics)); | |
| 335 } | |
| 336 | |
| 337 void MediaPerceptionAPIManager::MediaPerceptionSignalHandler( | |
| 338 const mri::MediaPerception& media_perception_proto) { | |
| 339 EventRouter* router = EventRouter::Get(browser_context_); | |
| 340 if (!router || !router->HasEventListener( | |
|
tbarzic
2017/05/09 01:28:36
I think you'd be fine without HasEventListener che
Luke Sorenson
2017/05/09 21:05:44
Does it hurt to leave the check in? Can help with
tbarzic
2017/05/09 21:19:14
it doesn't really hurt, but it's not that useful e
Luke Sorenson
2017/05/10 18:50:16
Acknowledged.
| |
| 341 media_perception::OnMediaPerception::kEventName)) { | |
| 342 return; | |
| 343 } | |
| 344 media_perception::MediaPerception media_perception = | |
| 345 MediaPerceptionProtoToIdl(media_perception_proto); | |
| 346 std::unique_ptr<Event> event( | |
| 347 new Event(events::MEDIA_PERCEPTION_PRIVATE_ON_MEDIA_PERCEPTION, | |
| 348 media_perception::OnMediaPerception::kEventName, | |
| 349 media_perception::OnMediaPerception::Create(media_perception))); | |
| 350 router->BroadcastEvent(std::move(event)); | |
| 351 } | |
| 352 | |
| 353 } // namespace extensions | |
| OLD | NEW |