| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_ | |
| 6 #define COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 #include <memory> | |
| 10 #include <set> | |
| 11 #include <string> | |
| 12 #include <vector> | |
| 13 | |
| 14 #include "base/callback_forward.h" | |
| 15 #include "base/memory/scoped_vector.h" | |
| 16 #include "components/audio_modem/public/audio_modem_types.h" | |
| 17 #include "components/copresence/proto/enums.pb.h" | |
| 18 #include "components/copresence/public/copresence_constants.h" | |
| 19 #include "components/copresence/public/copresence_delegate.h" | |
| 20 #include "components/copresence/timed_map.h" | |
| 21 | |
| 22 namespace copresence { | |
| 23 | |
| 24 class CopresenceDelegate; | |
| 25 class CopresenceStateImpl; | |
| 26 class DirectiveHandler; | |
| 27 class GCMHandler; | |
| 28 class HttpPost; | |
| 29 class ReportRequest; | |
| 30 class RequestHeader; | |
| 31 class SubscribedMessage; | |
| 32 | |
| 33 // This class handles all communication with the copresence server. | |
| 34 // Clients provide a ReportRequest proto containing publishes, subscribes, | |
| 35 // and token observations they want to send to the server. The RpcHandler | |
| 36 // will fill in details like the RequestHeader and DeviceCapabilities, | |
| 37 // and dispatch the results of the server call to the appropriate parts | |
| 38 // of the system. | |
| 39 // | |
| 40 // To create an RpcHandler, clients will need to provide a few other classes | |
| 41 // that support its functionality. Notable among them is the CopresenceDelegate, | |
| 42 // an interface clients must implement to provide settings and functionality | |
| 43 // that may depend on the environment. See the definition in | |
| 44 // //components/copresence/public/copresence_delegate.h. | |
| 45 // | |
| 46 // Here is an example of creating and using an RpcHandler. | |
| 47 // The GCMHandler and CopresenceStateImpl are optional. | |
| 48 // | |
| 49 // MyDelegate delegate(...); | |
| 50 // copresence::DirectiveHandlerImpl directive_handler; | |
| 51 // | |
| 52 // RpcHandler handler(&delegate, | |
| 53 // &directive_handler, | |
| 54 // nullptr, | |
| 55 // nullptr, | |
| 56 // base::Bind(&HandleMessages)); | |
| 57 // | |
| 58 // std::unique_ptr<ReportRequest> request(new ReportRequest); | |
| 59 // (Fill in ReportRequest.) | |
| 60 // | |
| 61 // handler.SendReportRequest(std::move(request), | |
| 62 // "my_app_id", | |
| 63 // "", | |
| 64 // base::Bind(&HandleStatus)); | |
| 65 // | |
| 66 // The server will respond with directives, which get passed to the | |
| 67 // DirectiveHandlerImpl. | |
| 68 // | |
| 69 // Tokens from the audio modem should also be forwarded | |
| 70 // via ReportTokens() so that messages get delivered properly. | |
| 71 class RpcHandler final { | |
| 72 public: | |
| 73 // An HttpPost::ResponseCallback along with an HttpPost object to be deleted. | |
| 74 // Arguments: | |
| 75 // HttpPost*: The handler should take ownership of (i.e. delete) this object. | |
| 76 // int: The HTTP status code of the response. | |
| 77 // string: The contents of the response. | |
| 78 using PostCleanupCallback = base::Callback<void(HttpPost*, | |
| 79 int, | |
| 80 const std::string&)>; | |
| 81 | |
| 82 // Callback to allow tests to stub out HTTP POST behavior. | |
| 83 // Arguments: | |
| 84 // URLRequestContextGetter: Context for the HTTP POST request. | |
| 85 // string: Name of the rpc to invoke. URL format: server.google.com/rpc_name | |
| 86 // string: The API key to pass in the request. | |
| 87 // string: The auth token to pass with the request. | |
| 88 // MessageLite: Contents of POST request to be sent. This needs to be | |
| 89 // a (scoped) pointer to ease handling of the abstract MessageLite class. | |
| 90 // PostCleanupCallback: Receives the response to the request. | |
| 91 using PostCallback = | |
| 92 base::Callback<void(net::URLRequestContextGetter*, | |
| 93 const std::string&, | |
| 94 const std::string&, | |
| 95 const std::string&, | |
| 96 std::unique_ptr<google::protobuf::MessageLite>, | |
| 97 const PostCleanupCallback&)>; | |
| 98 | |
| 99 // Report rpc name to send to Apiary. | |
| 100 static const char kReportRequestRpcName[]; | |
| 101 | |
| 102 // Constructor. The CopresenceStateImpl and GCMHandler may be null. | |
| 103 // The first four parameters are owned by the caller and (if not null) | |
| 104 // must outlive the RpcHandler. | |
| 105 RpcHandler(CopresenceDelegate* delegate, | |
| 106 DirectiveHandler* directive_handler, | |
| 107 CopresenceStateImpl* state, | |
| 108 GCMHandler* gcm_handler, | |
| 109 const MessagesCallback& new_messages_callback, | |
| 110 const PostCallback& server_post_callback = PostCallback()); | |
| 111 | |
| 112 // Not copyable. | |
| 113 RpcHandler(const RpcHandler&) = delete; | |
| 114 void operator=(const RpcHandler&) = delete; | |
| 115 | |
| 116 ~RpcHandler(); | |
| 117 | |
| 118 // Sends a ReportRequest from a specific app, and get notified of completion. | |
| 119 void SendReportRequest(std::unique_ptr<ReportRequest> request, | |
| 120 const std::string& app_id, | |
| 121 const std::string& auth_token, | |
| 122 const StatusCallback& callback); | |
| 123 | |
| 124 // Reports a set of tokens to the server for a given medium. | |
| 125 // Uses all active auth tokens (if any). | |
| 126 void ReportTokens(const std::vector<audio_modem::AudioToken>& tokens); | |
| 127 | |
| 128 private: | |
| 129 // A queued ReportRequest along with its metadata. | |
| 130 struct PendingRequest { | |
| 131 PendingRequest(std::unique_ptr<ReportRequest> report, | |
| 132 const std::string& app_id, | |
| 133 bool authenticated, | |
| 134 const StatusCallback& callback); | |
| 135 ~PendingRequest(); | |
| 136 | |
| 137 std::unique_ptr<ReportRequest> report; | |
| 138 const std::string app_id; | |
| 139 const bool authenticated; | |
| 140 const StatusCallback callback; | |
| 141 }; | |
| 142 | |
| 143 friend class RpcHandlerTest; | |
| 144 | |
| 145 // Before accepting any other calls, the server requires registration, | |
| 146 // which is tied to the auth token (or lack thereof) used to call Report. | |
| 147 void RegisterDevice(bool authenticated); | |
| 148 | |
| 149 // Device registration has completed. Send the requests that it was blocking. | |
| 150 void ProcessQueuedRequests(bool authenticated); | |
| 151 | |
| 152 // Sends a ReportRequest from Chrome itself, i.e. no app id. | |
| 153 void ReportOnAllDevices(std::unique_ptr<ReportRequest> request); | |
| 154 | |
| 155 // Stores a GCM ID and send it to the server if needed. | |
| 156 void RegisterGcmId(const std::string& gcm_id); | |
| 157 | |
| 158 // Server call response handlers. | |
| 159 void RegisterResponseHandler(bool authenticated, | |
| 160 bool gcm_pending, | |
| 161 HttpPost* completed_post, | |
| 162 int http_status_code, | |
| 163 const std::string& response_data); | |
| 164 void ReportResponseHandler(const StatusCallback& status_callback, | |
| 165 HttpPost* completed_post, | |
| 166 int http_status_code, | |
| 167 const std::string& response_data); | |
| 168 | |
| 169 // Removes unpublished or unsubscribed operations from the directive handlers. | |
| 170 void ProcessRemovedOperations(const ReportRequest& request); | |
| 171 | |
| 172 // Adds all currently playing tokens to the update signals in this report | |
| 173 // request. This ensures that the server doesn't keep issueing new tokens to | |
| 174 // us when we're already playing valid tokens. | |
| 175 void AddPlayingTokens(ReportRequest* request); | |
| 176 | |
| 177 void DispatchMessages( | |
| 178 const google::protobuf::RepeatedPtrField<SubscribedMessage>& | |
| 179 subscribed_messages); | |
| 180 | |
| 181 RequestHeader* CreateRequestHeader(const std::string& app_id, | |
| 182 const std::string& device_id) const; | |
| 183 | |
| 184 // Wrapper for the http post constructor. This is the default way | |
| 185 // to contact the server, but it can be overridden for testing. | |
| 186 void SendHttpPost( | |
| 187 net::URLRequestContextGetter* url_context_getter, | |
| 188 const std::string& rpc_name, | |
| 189 const std::string& api_key, | |
| 190 const std::string& auth_token, | |
| 191 std::unique_ptr<google::protobuf::MessageLite> request_proto, | |
| 192 const PostCleanupCallback& callback); | |
| 193 | |
| 194 // These belong to the caller. | |
| 195 CopresenceDelegate* const delegate_; | |
| 196 DirectiveHandler* const directive_handler_; | |
| 197 CopresenceStateImpl* state_; | |
| 198 GCMHandler* const gcm_handler_; | |
| 199 | |
| 200 MessagesCallback new_messages_callback_; | |
| 201 PostCallback server_post_callback_; | |
| 202 | |
| 203 ScopedVector<PendingRequest> pending_requests_queue_; | |
| 204 TimedMap<std::string, bool> invalid_audio_token_cache_; | |
| 205 std::set<HttpPost*> pending_posts_; | |
| 206 std::set<bool> pending_registrations_; | |
| 207 std::string auth_token_; | |
| 208 std::string gcm_id_; | |
| 209 }; | |
| 210 | |
| 211 } // namespace copresence | |
| 212 | |
| 213 #endif // COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_ | |
| OLD | NEW |