#ifndef COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_
#define COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_
+#include <map>
#include <set>
#include <string>
#include <vector>
-#include "base/callback.h"
+#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "components/copresence/proto/enums.pb.h"
#include "components/copresence/public/copresence_delegate.h"
-#include "components/copresence/public/whispernet_client.h"
-#include "components/copresence/rpc/http_post.h"
#include "components/copresence/timed_map.h"
namespace copresence {
+struct AudioToken;
+class CopresenceDelegate;
class DirectiveHandler;
+class GCMHandler;
+class HttpPost;
class ReportRequest;
class RequestHeader;
class SubscribedMessage;
// A callback to indicate whether handler initialization succeeded.
typedef base::Callback<void(bool)> SuccessCallback;
+ // An HttpPost::ResponseCallback along with an HttpPost object to be deleted.
+ // Arguments:
+ // HttpPost*: The handler should take ownership of (i.e. delete) this object.
+ // int: The HTTP status code of the response.
+ // string: The contents of the response.
+ typedef base::Callback<void(HttpPost*, int, const std::string&)>
+ PostCleanupCallback;
+
+ // Callback to allow tests to stub out HTTP POST behavior.
+ // Arguments:
+ // URLRequestContextGetter: Context for the HTTP POST request.
+ // string: Name of the rpc to invoke. URL format: server.google.com/rpc_name
+ // string: The API key to pass in the request.
+ // string: The auth token to pass with the request.
+ // MessageLite: Contents of POST request to be sent. This needs to be
+ // a (scoped) pointer to ease handling of the abstract MessageLite class.
+ // PostCleanupCallback: Receives the response to the request.
+ typedef base::Callback<void(net::URLRequestContextGetter*,
+ const std::string&,
+ const std::string&,
+ const std::string&,
+ scoped_ptr<google::protobuf::MessageLite>,
+ const PostCleanupCallback&)> PostCallback;
+
// Report rpc name to send to Apiary.
static const char kReportRequestRpcName[];
- // Constructor. |delegate| is owned by the caller,
- // and must be valid as long as the RpcHandler exists.
- explicit RpcHandler(CopresenceDelegate* delegate);
+ // Constructor. |delegate| and |directive_handler|
+ // are owned by the caller and must outlive the RpcHandler.
+ // |server_post_callback| should be set only by tests.
+ RpcHandler(CopresenceDelegate* delegate,
+ DirectiveHandler* directive_handler,
+ GCMHandler* gcm_handler,
+ const PostCallback& server_post_callback = PostCallback());
virtual ~RpcHandler();
- // Clients must call this and wait for |init_done_callback|
- // to be called before invoking any other methods.
- void Initialize(const SuccessCallback& init_done_callback);
-
- // Send a report request.
- void SendReportRequest(scoped_ptr<ReportRequest> request);
+ // Send a ReportRequest from a specific app, and get notified of completion.
void SendReportRequest(scoped_ptr<ReportRequest> request,
const std::string& app_id,
+ const std::string& auth_token,
const StatusCallback& callback);
// Report a set of tokens to the server for a given medium.
+ // Uses all active auth tokens (if any).
void ReportTokens(const std::vector<AudioToken>& tokens);
- // Create the directive handler and connect it to
- // the whispernet client specified by the delegate.
- void ConnectToWhispernet();
-
private:
- // An HttpPost::ResponseCallback prepended with an HttpPost object
- // that needs to be deleted.
- typedef base::Callback<void(HttpPost*, int, const std::string&)>
- PostCleanupCallback;
-
- // Callback to allow tests to stub out HTTP POST behavior.
- // Arguments:
- // URLRequestContextGetter: Context for the HTTP POST request.
- // string: Name of the rpc to invoke. URL format: server.google.com/rpc_name
- // MessageLite: Contents of POST request to be sent. This needs to be
- // a (scoped) pointer to ease handling of the abstract MessageLite class.
- // ResponseCallback: Receives the response to the request.
- typedef base::Callback<void(net::URLRequestContextGetter*,
- const std::string&,
- scoped_ptr<google::protobuf::MessageLite>,
- const PostCleanupCallback&)> PostCallback;
+ // A queued ReportRequest along with its metadata.
+ struct PendingRequest {
+ PendingRequest(scoped_ptr<ReportRequest> report,
+ const std::string& app_id,
+ const std::string& auth_token,
+ const StatusCallback& callback);
+ ~PendingRequest();
+
+ scoped_ptr<ReportRequest> report;
+ const std::string app_id;
+ const std::string auth_token;
+ const StatusCallback callback;
+ };
friend class RpcHandlerTest;
- void RegisterResponseHandler(const SuccessCallback& init_done_callback,
+ // Before accepting any other calls, the server requires registration,
+ // which is tied to the auth token (or lack thereof) used to call Report.
+ void RegisterForToken(const std::string& auth_token);
+
+ // Device registration has completed. Send the requests that it was blocking.
+ void ProcessQueuedRequests(const std::string& auth_token);
+
+ // Send a ReportRequest from Chrome itself, i.e. no app id.
+ void SendReportRequest(scoped_ptr<ReportRequest> request,
+ const std::string& auth_token);
+
+ // Store a GCM ID and send it to the server if needed.
+ void RegisterGcmId(const std::string& gcm_id);
+
+ // Server call response handlers.
+ void RegisterResponseHandler(const std::string& auth_token,
+ bool gcm_pending,
HttpPost* completed_post,
int http_status_code,
const std::string& response_data);
const google::protobuf::RepeatedPtrField<SubscribedMessage>&
subscribed_messages);
- RequestHeader* CreateRequestHeader(const std::string& client_name) const;
+ RequestHeader* CreateRequestHeader(const std::string& client_name,
+ const std::string& device_id) const;
+ // Post a request to the server. The request should be in proto format.
template <class T>
void SendServerRequest(const std::string& rpc_name,
+ const std::string& device_id,
const std::string& app_id,
+ const std::string& auth_token,
scoped_ptr<T> request,
const PostCleanupCallback& response_handler);
// to contact the server, but it can be overridden for testing.
void SendHttpPost(net::URLRequestContextGetter* url_context_getter,
const std::string& rpc_name,
+ const std::string& api_key,
+ const std::string& auth_token,
scoped_ptr<google::protobuf::MessageLite> request_proto,
const PostCleanupCallback& callback);
- // This method receives the request to encode a token and forwards it to
- // whispernet, setting the samples return callback to samples_callback.
- void AudioDirectiveListToWhispernetConnector(
- const std::string& token,
- bool audible,
- const WhispernetClient::SamplesCallback& samples_callback);
+ // These belong to the caller.
+ CopresenceDelegate* const delegate_;
+ DirectiveHandler* const directive_handler_;
+ GCMHandler* const gcm_handler_;
- CopresenceDelegate* delegate_; // Belongs to the caller.
- TimedMap<std::string, bool> invalid_audio_token_cache_;
PostCallback server_post_callback_;
- std::string device_id_;
- scoped_ptr<DirectiveHandler> directive_handler_;
+ ScopedVector<PendingRequest> pending_requests_queue_;
+ TimedMap<std::string, bool> invalid_audio_token_cache_;
+ std::map<std::string, std::string> device_id_by_auth_token_;
std::set<HttpPost*> pending_posts_;
+ std::string gcm_id_;
DISALLOW_COPY_AND_ASSIGN(RpcHandler);
};