1 // Copyright 2020 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 #ifndef CAST_SENDER_CAST_APP_AVAILABILITY_TRACKER_H_
6 #define CAST_SENDER_CAST_APP_AVAILABILITY_TRACKER_H_
7 
8 #include <map>
9 #include <string>
10 #include <vector>
11 
12 #include "cast/sender/channel/message_util.h"
13 #include "cast/sender/public/cast_media_source.h"
14 #include "platform/api/time.h"
15 
16 namespace openscreen {
17 namespace cast {
18 
19 // Tracks device queries and their extracted Cast app IDs and their
20 // availabilities on discovered devices.
21 // Example usage:
22 ///
23 // (1) A page is interested in a Cast URL (e.g. by creating a
24 // PresentationRequest with the URL) like "cast:foo". To register the source to
25 // be tracked:
26 //   CastAppAvailabilityTracker tracker;
27 //   auto source = CastMediaSource::From("cast:foo");
28 //   auto new_app_ids = tracker.RegisterSource(source.value());
29 //
30 // (2) The set of app IDs returned by the tracker can then be used by the caller
31 // to send an app availability request to each of the discovered devices.
32 //
33 // (3) Once the caller knows the availability value for a (device, app) pair, it
34 // may inform the tracker to update its results:
35 //   auto affected_sources =
36 //       tracker.UpdateAppAvailability(device_id, app_id, {availability, now});
37 //
38 // (4) The tracker returns a subset of discovered sources that were affected by
39 // the update. The caller can then call |GetAvailableDevices()| to get the
40 // updated results for each affected source.
41 //
42 // (5a): At any time, the caller may call |RemoveResultsForDevice()| to remove
43 // cached results pertaining to the device, when it detects that a device is
44 // removed or no longer valid.
45 //
46 // (5b): At any time, the caller may call |GetAvailableDevices()| (even before
47 // the source is registered) to determine if there are cached results available.
48 // TODO(crbug.com/openscreen/112): Device -> Receiver renaming.
49 class CastAppAvailabilityTracker {
50  public:
51   // The result of an app availability request and the time when it is obtained.
52   struct AppAvailability {
53     AppAvailabilityResult availability;
54     Clock::time_point time;
55   };
56 
57   CastAppAvailabilityTracker();
58   ~CastAppAvailabilityTracker();
59 
60   CastAppAvailabilityTracker(const CastAppAvailabilityTracker&) = delete;
61   CastAppAvailabilityTracker& operator=(const CastAppAvailabilityTracker&) =
62       delete;
63 
64   // Registers |source| with the tracker. Returns a list of new app IDs that
65   // were previously not known to the tracker.
66   std::vector<std::string> RegisterSource(const CastMediaSource& source);
67 
68   // Unregisters the source given by |source| or |source_id| with the tracker.
69   void UnregisterSource(const std::string& source_id);
70   void UnregisterSource(const CastMediaSource& source);
71 
72   // Updates the availability of |app_id| on |device_id| to |availability|.
73   // Returns a list of registered CastMediaSources for which the set of
74   // available devices might have been updated by this call. The caller should
75   // call |GetAvailableDevices| with the returned CastMediaSources to get the
76   // updated lists.
77   std::vector<CastMediaSource> UpdateAppAvailability(
78       const std::string& device_id,
79       const std::string& app_id,
80       AppAvailability availability);
81 
82   // Removes all results associated with |device_id|, i.e. when the device
83   // becomes invalid.  Returns a list of registered CastMediaSources for which
84   // the set of available devices might have been updated by this call. The
85   // caller should call |GetAvailableDevices| with the returned CastMediaSources
86   // to get the updated lists.
87   std::vector<CastMediaSource> RemoveResultsForDevice(
88       const std::string& device_id);
89 
90   // Returns a list of registered CastMediaSources supported by |device_id|.
91   std::vector<CastMediaSource> GetSupportedSources(
92       const std::string& device_id) const;
93 
94   // Returns the availability for |app_id| on |device_id| and the time at which
95   // the availability was determined. If availability is kUnknown, then the time
96   // may be null (e.g. if an availability request was never sent).
97   AppAvailability GetAvailability(const std::string& device_id,
98                                   const std::string& app_id) const;
99 
100   // Returns a list of registered app IDs.
101   std::vector<std::string> GetRegisteredApps() const;
102 
103   // Returns a list of device IDs compatible with |source|, using the current
104   // availability info.
105   std::vector<std::string> GetAvailableDevices(
106       const CastMediaSource& source) const;
107 
108  private:
109   // App ID to availability.
110   using AppAvailabilityMap = std::map<std::string, AppAvailability>;
111 
112   // Registered sources and corresponding CastMediaSources.
113   std::map<std::string, CastMediaSource> registered_sources_;
114 
115   // App IDs tracked and the number of registered sources containing them.
116   std::map<std::string, int> registration_count_by_app_id_;
117 
118   // IDs and app availabilities of known devices.
119   std::map<std::string, AppAvailabilityMap> app_availabilities_;
120 };
121 
122 }  // namespace cast
123 }  // namespace openscreen
124 
125 #endif  // CAST_SENDER_CAST_APP_AVAILABILITY_TRACKER_H_
126